Enhanced Citations: Server-Side Rendering Fix
Version Implemented: 0.229.001
Overview
Fixed the critical authentication error in enhanced citations: ValueError: Either user_delegation_key or account_key must be provided. by implementing server-side rendering instead of SAS URL generation.
Problem Description
Original Error
ValueError: Either user_delegation_key or account_key must be provided.
at generate_blob_sas() in route_enhanced_citations.py
Root Cause
The enhanced citations system was attempting to generate SAS (Shared Access Signature) URLs for blob storage access, which required storage account keys that may not be configured in all environments. The generate_blob_sas() function requires either:
- A storage account key (
account_key) - User delegation key for Azure AD authentication
Impact
- Enhanced citations failed to load for PDFs, images, videos, and audio
- Users experienced 500 Internal Server Error when clicking citations
- System fell back to text citations, degrading user experience
Solution: Server-Side Rendering
Approach
Instead of generating SAS URLs and exposing them to the frontend, the Flask application now serves media content directly through its existing blob storage client connections.
Architecture Changes
Backend (route_enhanced_citations.py)
Before:
# Generated SAS URLs with account keys
sas_token = generate_blob_sas(
account_name=blob_service_client.account_name,
account_key=settings.get("office_docs_key"), # ❌ May not be available
permission=BlobSasPermissions(read=True),
expiry=datetime.utcnow() + timedelta(hours=1)
)
return jsonify({"image_url": f"{base_url}?{sas_token}"})
After:
# Direct content serving using existing client
blob_client = container_client.get_blob_client(blob_name)
blob_data = blob_client.download_blob()
content = blob_data.readall()
return Response(
content,
content_type=content_type,
headers={
'Content-Length': str(len(content)),
'Cache-Control': 'private, max-age=300',
'Accept-Ranges': 'bytes'
}
)
Frontend (chat-enhanced-citations.js)
Before:
// Fetched JSON with SAS URL
fetch(`/api/enhanced_citations/image?doc_id=${docId}`)
.then(resp => resp.json())
.then(data => {
img.src = data.image_url; // ❌ SAS URL
});
After:
// Direct endpoint as media source
const imageUrl = `/api/enhanced_citations/image?doc_id=${docId}`;
img.src = imageUrl; // ✅ Direct server-side rendering
Benefits
Security
- ✅ No exposure of storage credentials
- ✅ Server-side access control maintained
- ✅ No temporary URL leakage
- ✅ Consistent authentication via Flask decorators
Reliability
- ✅ Uses existing blob storage client connections
- ✅ No dependency on account key configuration
- ✅ Leverages DefaultAzureCredential for authentication
- ✅ Eliminates SAS token expiry issues
Performance
- ✅ Direct content streaming
- ✅ Proper caching headers (5-minute cache)
- ✅ Range request support for video/audio seeking
- ✅ Reduced network round trips
Maintainability
- ✅ Simpler code without SAS generation complexity
- ✅ Consistent with existing Flask patterns
- ✅ Better error handling and logging
- ✅ Easier debugging and monitoring
Implementation Details
Content Type Handling
# Automatic content type detection
content_type, _ = mimetypes.guess_type(file_name)
# Fallback content types for common formats
if file_ext == '.jpg': content_type = 'image/jpeg'
elif file_ext == '.mp4': content_type = 'video/mp4'
elif file_ext == '.mp3': content_type = 'audio/mpeg'
HTTP Headers
headers = {
'Content-Length': str(len(content)),
'Cache-Control': 'private, max-age=300', # 5-minute cache
'Content-Disposition': f'inline; filename="{filename}"',
'Accept-Ranges': 'bytes' # Video/audio seeking
}
Workspace Support
- ✅ Personal workspaces:
storage_account_user_documents_container_name - ✅ Group workspaces:
storage_account_group_documents_container_name - ✅ Public workspaces:
storage_account_public_documents_container_name
Testing
Functional Test Results
Enhanced Citations Server-Side Rendering Fix Test
=======================================================
🔍 Testing Enhanced Citations Server-Side Rendering... ✅
🔍 Testing Frontend Server-Side Integration... ✅
🔍 Testing Error Scenario Resolution... ✅
📊 Test Results: 3/3 tests passed
🎉 All tests passed!
Manual Testing
- Upload PDF document → Enhanced citations work without SAS errors
- Upload image files → Display in modal viewer via server-side rendering
- Upload video files → Play with timestamp navigation
- Upload audio files → Play with timestamp navigation
Migration Guide
For Developers
No changes required in:
- Document upload processes
- Citation generation logic
- Frontend citation clicking behavior
- User authentication flows
For Administrators
Benefits automatically apply:
- No additional configuration needed
- Works with existing blob storage setup
- Maintains all existing security policies
- No performance impact on other features
Version Information
- Fixed in Version: 0.228.005
- Related Files:
route_enhanced_citations.py- Backend server-side renderingchat-enhanced-citations.js- Frontend direct media loadingtest_enhanced_citations_server_side_rendering_fix.py- Functional test
Future Enhancements
The server-side rendering approach enables:
- 🔄 Response compression for large files
- 📊 Access logging and analytics
- 🔒 Enhanced access control policies
- ⚡ Content caching and CDN integration
- 🎯 Bandwidth throttling for large media files
Summary
The server-side rendering fix resolves the SAS URL authentication error while providing a more secure, reliable, and maintainable solution for enhanced citations. Users can now seamlessly view images, PDFs, videos, and audio files through enhanced citation modals without any configuration dependencies.