Refactor API under /auth/api
This commit is contained in:
+35
-21
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user