Refactor API under /auth/api

This commit is contained in:
Leo Vasanko
2025-09-02 14:32:19 -06:00
parent 859cc9ed41
commit 312d23b79a
7 changed files with 208 additions and 240 deletions
+35 -21
View File
@@ -4,12 +4,13 @@ from contextlib import asynccontextmanager
from pathlib import Path
from fastapi import Cookie, FastAPI, HTTPException, Query, Request, Response
from fastapi.responses import FileResponse, JSONResponse
from fastapi.responses import FileResponse, JSONResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from . import admin, authz, ws
from .api import register_api_routes
from .reset import register_reset_routes
from passkey.util import passphrase
from ..globals import passkey as global_passkey
from . import admin, api, authz, ws
STATIC_DIR = Path(__file__).parent.parent / "frontend-build"
@@ -51,6 +52,7 @@ async def lifespan(app: FastAPI): # pragma: no cover - startup path
app = FastAPI(lifespan=lifespan)
app.mount("/auth/ws", ws.app)
app.mount("/auth/admin", admin.app)
app.mount("/auth/api", api.app)
# Global exception handlers
@@ -67,6 +69,35 @@ async def general_exception_handler(request: Request, exc: Exception):
return JSONResponse(status_code=500, content={"detail": "Internal server error"})
# Serve static files
app.mount(
"/auth/assets", StaticFiles(directory=STATIC_DIR / "assets"), name="static assets"
)
@app.get("/auth/")
async def redirect_to_index():
"""Serve the main authentication app."""
return FileResponse(STATIC_DIR / "index.html")
@app.get("/auth/{reset_token}")
async def reset_authentication(request: Request, reset_token: str):
"""Validate reset token and redirect with it as query parameter (no cookies).
After validation we 303 redirect to /auth/?reset=<token>. The frontend will:
- Read the token from location.search
- Use it via Authorization header or websocket query param
- history.replaceState to remove it from the address bar/history
"""
if not passphrase.is_well_formed(reset_token):
raise HTTPException(status_code=404)
origin = global_passkey.instance.origin
# Do not verify existence/expiry here; frontend + user-info endpoint will handle invalid tokens.
url = f"{origin}/auth/?reset={reset_token}"
return RedirectResponse(url=url, status_code=303)
@app.get("/auth/forward-auth")
async def forward_authentication(request: Request, perm=Query(None), auth=Cookie(None)):
"""A validation endpoint to use with Caddy forward_auth or Nginx auth_request.
@@ -86,20 +117,3 @@ async def forward_authentication(request: Request, perm=Query(None), auth=Cookie
)
except HTTPException as e:
return FileResponse(STATIC_DIR / "index.html", e.status_code)
# Serve static files
app.mount(
"/auth/assets", StaticFiles(directory=STATIC_DIR / "assets"), name="static assets"
)
@app.get("/auth/")
async def redirect_to_index():
"""Serve the main authentication app."""
return FileResponse(STATIC_DIR / "index.html")
# Register API routes
register_api_routes(app)
register_reset_routes(app)