Advanced Authentication

Integrate JWTs, manage complex scopes, and handle user context securely.

JWT Validation & User Context

A common pattern is decoding a JWT, validating it, and attaching the user object to the request state.

import jwt
from fastapi import HTTPException

async def jwt_auth_handler(request: Request, roles: list[str] = None) -> bool:
    auth_header = request.headers.get("Authorization")
    if not auth_header or not auth_header.startswith("Bearer "):
        return False
        
    token = auth_header.split(" ")[1]
    
    try:
        # Decode token
        payload = jwt.decode(token, "APP_SECRET", algorithms=["HS256"])
        
        # Attach user to request state for endpoint access
        request.state.user = payload
        
        # Role Check
        if roles:
            user_roles = payload.get("roles", [])
            has_permission = any(role in user_roles for role in roles)
            if not has_permission:
                raise HTTPException(status_code=403, detail="Insufficient Permissions")
                
        return True
        
    except jwt.ExpiredSignatureError:
        raise HTTPException(status_code=401, detail="Token expired")
    except jwt.InvalidTokenError:
        return False # Invalid token

Accessing User Data

Data attached to request.state in the auth handler becomes available in your endpoints.

routes/profile.py
class UserProfile(Route):
    @auth(True)
    async def get(self, request: Request):
        # Access user data set by the auth handler
        user_id = request.state.user["id"]
        return {"id": user_id, "name": request.state.user["name"]}

Detailed Signature

def auth(
    enabled: bool = True, *, 
    roles: list[str] = None, 
    scopes: list[str] = None, 
    require_all: bool = False, 
    custom_error: str = None
)
  • roles: List of required user roles (e.g., ["admin", "mod"]).
  • scopes: List of required OAuth scopes (e.g., ["read:users"]).
  • require_all: If True, user must have all listed roles/scopes. If False, any match grants access.
  • custom_error: Custom message for 403 Forbidden responses.