enforce: auth required on ALL API endpoints except login
Some checks failed
Deploy Tracker / deploy (push) Failing after 4s

This commit is contained in:
markov 2026-02-25 11:24:01 +01:00
parent 8b993abc37
commit 0840e38849

View File

@ -89,47 +89,48 @@ app = FastAPI(
lifespan=lifespan,
)
# Paths that don't require auth
NO_AUTH_PATHS = {"/health", "/docs", "/openapi.json", "/ws"}
# API paths that don't require auth
NO_AUTH_API = {"/api/v1/auth/login"}
@app.middleware("http")
async def auth_middleware(request: Request, call_next):
"""Verify token for REST API requests."""
"""Verify token for all API requests (except login)."""
path = request.url.path
# Skip auth for non-API paths and excluded paths
if not path.startswith("/api/") and path not in NO_AUTH_PATHS:
# WS and health don't need REST auth
pass
elif path.startswith("/api/"):
auth_header = request.headers.get("authorization", "")
token = None
if auth_header.startswith("Bearer "):
token = auth_header[7:]
elif request.query_params.get("token"):
token = request.query_params["token"]
if token:
# Check agent token
async with async_session() as db:
result = await db.execute(select(Member).where(Member.token == token))
member = result.scalar_one_or_none()
if member:
request.state.member = member
else:
# Try JWT
from tracker.api.auth import decode_jwt
try:
payload = decode_jwt(token)
result = await db.execute(select(Member).where(Member.id == payload["sub"]))
member = result.scalar_one_or_none()
if member:
request.state.member = member
except Exception:
pass
# Don't enforce auth yet — BFF uses its own token via proxy
# TODO: enforce when all clients are updated
if not path.startswith("/api/") or path in NO_AUTH_API:
return await call_next(request)
# Extract token from header or query param
auth_header = request.headers.get("authorization", "")
token = None
if auth_header.startswith("Bearer "):
token = auth_header[7:]
elif request.query_params.get("token"):
token = request.query_params["token"]
if not token:
return JSONResponse(status_code=401, content={"error": "Authentication required"})
# Resolve member from token
async with async_session() as db:
# Try agent token first
result = await db.execute(select(Member).where(Member.token == token))
member = result.scalar_one_or_none()
if not member:
# Try JWT
from tracker.api.auth import decode_jwt
try:
payload = decode_jwt(token)
result = await db.execute(select(Member).where(Member.id == payload["sub"]))
member = result.scalar_one_or_none()
except Exception:
pass
if not member:
return JSONResponse(status_code=401, content={"error": "Invalid or expired token"})
request.state.member = member
return await call_next(request)