Files
ITWorx_MCP_Hub-Public/services/control_api/auth/router.py
T

71 lines
2.5 KiB
Python

"""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