Remove some confusion between exchange and set-session endpoints, all using set-session now with a bearer code. Using codes in remote auth as well. Full separation of cookie and OIDC codes.
This commit is contained in:
+24
-37
@@ -3,7 +3,6 @@ from contextlib import suppress
|
||||
from datetime import UTC, datetime, timedelta
|
||||
|
||||
from fastapi import (
|
||||
Body,
|
||||
Depends,
|
||||
FastAPI,
|
||||
HTTPException,
|
||||
@@ -68,34 +67,6 @@ async def general_exception_handler(
|
||||
return JSONResponse(status_code=500, content={"detail": "Internal server error"})
|
||||
|
||||
|
||||
@app.post("/exchange")
|
||||
async def exchange_code(
|
||||
request: Request,
|
||||
response: Response,
|
||||
code: str = Body(..., embed=True),
|
||||
):
|
||||
"""Exchange a session code for setting the session cookie.
|
||||
|
||||
Called by frontend after WebSocket authentication.
|
||||
The code is ephemeral (60s TTL) and can only be used once.
|
||||
"""
|
||||
auth_code = authcode.codes.pop(code, None)
|
||||
if not auth_code:
|
||||
raise HTTPException(status_code=400, detail="Invalid or expired code")
|
||||
|
||||
secret = auth_code.session_key
|
||||
|
||||
# Verify the session exists
|
||||
host = hostutil.normalize_host(request.headers.get("host", ""))
|
||||
ctx = db.data().session_ctx(secret, host)
|
||||
if not ctx:
|
||||
raise HTTPException(status_code=400, detail="Session not found")
|
||||
|
||||
# Set the session cookie
|
||||
session.set_session_cookie(response, secret)
|
||||
return {"status": "ok", "user": str(ctx.user.uuid)}
|
||||
|
||||
|
||||
@app.post("/validate")
|
||||
async def validate_token(
|
||||
request: Request,
|
||||
@@ -294,13 +265,29 @@ async def api_logout(request: Request, response: Response, auth=AUTH_COOKIE):
|
||||
async def api_set_session(
|
||||
request: Request, response: Response, auth=Depends(bearer_auth)
|
||||
):
|
||||
"""Exchange an auth code for setting the session cookie.
|
||||
|
||||
Called by frontend after WebSocket authentication.
|
||||
The code is ephemeral (60s TTL) and can only be used once.
|
||||
"""
|
||||
if not auth or not auth.credentials:
|
||||
raise HTTPException(401, "Bearer token required")
|
||||
ctx = db.data().session_ctx(auth.credentials, request.headers.get("host"))
|
||||
raise HTTPException(400, "Bearer token required")
|
||||
|
||||
# Verify host is provided
|
||||
host = hostutil.normalize_host(request.headers.get("host", ""))
|
||||
if not host:
|
||||
raise HTTPException(400, "Host header required")
|
||||
|
||||
a = authcode.consume_cookie(auth.credentials)
|
||||
if not a:
|
||||
raise HTTPException(401, "Code expired or already used")
|
||||
|
||||
secret = a.session_key
|
||||
|
||||
# Verify the session exists
|
||||
ctx = db.data().session_ctx(secret, host)
|
||||
if not ctx:
|
||||
raise HTTPException(401, "Session expired")
|
||||
session.set_session_cookie(response, auth.credentials)
|
||||
return {
|
||||
"message": "Session cookie set successfully",
|
||||
"user": str(ctx.user.uuid),
|
||||
}
|
||||
raise HTTPException(401, f"Session not found on {host}")
|
||||
|
||||
session.set_session_cookie(response, secret)
|
||||
return {"status": "ok", "user": str(ctx.user.uuid)}
|
||||
|
||||
Reference in New Issue
Block a user