"""FastAPI routes for the same-origin management BFF.""" from __future__ import annotations from fastapi import APIRouter, HTTPException, Request, Response, status from fastapi.responses import RedirectResponse from .bff import BFFService from .errors import AuthError def _safe_error(exc: AuthError) -> HTTPException: return HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail={"code": exc.code, "message": exc.public_message}, headers={"Cache-Control": "no-store"}, ) def build_auth_router(bff: BFFService) -> APIRouter: router = APIRouter(prefix="/auth", tags=["auth"]) @router.get("/login", include_in_schema=False) def login() -> RedirectResponse: try: return RedirectResponse( bff.begin_login(), status_code=status.HTTP_307_TEMPORARY_REDIRECT ) except AuthError as exc: raise _safe_error(exc) from exc @router.get("/callback", include_in_schema=False) def callback(code: str, state: str) -> RedirectResponse: try: session = bff.complete_login(code=code, state=state) except AuthError as exc: raise _safe_error(exc) from exc response = RedirectResponse("/", status_code=status.HTTP_303_SEE_OTHER) response.headers["Set-Cookie"] = session.set_cookie response.headers["Cache-Control"] = "no-store" return response @router.get("/session") def session(request: Request, response: Response) -> dict[str, object]: cookie = request.cookies.get(bff.settings.cookie_name) if cookie is None: response.headers["Cache-Control"] = "no-store" return {"authenticated": False} try: metadata = bff.session_metadata(cookie) record = bff.sessions.get(cookie) except AuthError as exc: raise _safe_error(exc) from exc return { "authenticated": True, "csrf_token": record.csrf_token, "session": metadata.model_dump(mode="json"), } @router.post("/logout", status_code=status.HTTP_204_NO_CONTENT, response_model=None) def logout(request: Request, response: Response) -> None: try: cookie = request.cookies.get(bff.settings.cookie_name) clear_cookie = bff.logout(cookie, request.headers.get("X-CSRF-Token")) except AuthError as exc: raise _safe_error(exc) from exc response.headers["Set-Cookie"] = clear_cookie response.headers["Cache-Control"] = "no-store" return router