odysseus-dev/odysseus · warning · HTTPException
Authentication required
Error message
Authentication required
What it means
403 raised by GET /api/documents/{session_id} when get_current_user(request) returns no user and authentication is not disabled (i.e. the app is running with auth enabled). It is an explicit gate: anonymous callers may only list session documents when the deployment intentionally runs auth-free.
Source
Thrown at routes/document/document_routes.py:452
"total": total,
"languages": languages,
"session_count": session_count,
}
except Exception as e:
logger.error(f"Failed to fetch document library: {e}")
raise HTTPException(500, f"Failed to fetch document library: {e}")
finally:
db.close()
# ---- GET /api/documents/{session_id} ----
@router.get("/api/documents/{session_id}")
async def list_documents(request: Request, session_id: str) -> List[Dict[str, Any]]:
user = get_current_user(request)
db = SessionLocal()
try:
if not user:
if not _auth_disabled():
raise HTTPException(403, "Authentication required")
# v2 review HIGH-9: raise 403 explicitly when the caller
# can't see this session, instead of returning [] which the
# UI treats identically to "no docs" and silently masks
# auth failures.
_get_session_or_404(db, session_id, user)
q = db.query(Document).filter(
Document.session_id == session_id
)
if user:
q = q.filter(or_(Document.owner == user, Document.owner.is_(None)))
docs = q.order_by(Document.created_at.desc()).all()
return [_doc_to_dict(d) for d in docs]
finally:
db.close()
# ---- GET /api/document/{doc_id} ----
@router.get("/api/document/{doc_id}")
async def get_document(request: Request, doc_id: str) -> Dict[str, Any]:View on GitHub (pinned to f9235ebbf1)
Solutions
- Send valid credentials with the request (session cookie or auth header) as the app expects.
- If this deployment is intentionally auth-free, enable the app's auth-disabled mode so _auth_disabled() returns true.
- Check CORS/proxy config so cookies survive the hop (withCredentials, same-site settings).
- Re-login to obtain a fresh token if the old one expired or the user was recreated.
Example fix
// before
fetch(`/api/documents/${sessionId}`) // no credentials -> 403
// after
fetch(`/api/documents/${sessionId}`, { credentials: 'include' }) Defensive patterns
Strategy: validation
Validate before calling
async function listDocs(sessionId) {
if (!auth.currentUser()) return redirect('/login?next=' + encodeURIComponent(location.pathname));
return api.get(`/api/documents/${sessionId}`, { credentials: 'include' });
} Type guard
function hasUser(): boolean { return Boolean(auth.currentUser()); } Try / catch
try { await api.get(url); }
catch (e) { if (e.status === 403 && e.message === 'Authentication required') { await auth.refreshOrLogin(); return api.get(url, { credentials: 'include' }); } throw e; } Prevention
- Attach credentials to every API call
- Configure CORS with credentials and correct origin
- Handle token expiry with a re-login flow before the request, not after
When it happens
Trigger: Request arrives without valid auth credentials (missing/expired session cookie or token); auth enabled in config while the client assumed open access; a proxy strips the auth header/cookie; the user record was deleted so the token no longer resolves.
Common situations: Frontend dev server not forwarding cookies (different port/domain without CORS credentials); token expiry after a long idle period; environment flipped from AUTH_DISABLED=1 to auth-enabled between environments; logged-in user removed from the user store.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Admin only
- Action '{action}' requires admin privileges
- Admin only
- Password is required
- Your account is not allowed to use model '{sess.model}'.
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/01afc69d34a9d337.
Report an issue: GitHub.