FastAPIAuth
Authentication for FastAPI applications.
FastAPIAuth
Bases: BaseAuth
Authentication for FastAPI apps.
RECOMMENDED: Use protect_app() to protect your entire application with one line.
Example (RECOMMENDED - protect entire app): from fastapi import FastAPI, Depends from cognito_auth.fastapi import FastAPIAuth
app = FastAPI()
auth = FastAPIAuth()
auth.protect_app(app, bypass={"/health"}) # Protects entire app except /health!
@app.get("/")
def index(user: User = Depends(auth.get_auth_user)):
return {"message": f"Welcome {user.email}!"}
@app.get("/health")
def health():
return {"status": "ok"}
Example (Alternative - protect specific routes): from fastapi import FastAPI, Depends from cognito_auth.fastapi import FastAPIAuth
app = FastAPI()
auth = FastAPIAuth()
@app.get("/public")
def public():
return {"message": "Public page"}
@app.get("/protected")
def protected(user: User = Depends(auth.get_auth_user)):
return {"message": f"Welcome {user.email}!"}
Source code in src/cognito_auth/fastapi.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | |
Functions
protect_app(app, bypass=None)
Protect the entire application with authentication.
This is the RECOMMENDED approach. Call this once after creating your app, and all routes will require authentication. Use get_auth_user() dependency to access the authenticated user.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
FastAPI
|
FastAPI application instance |
required |
bypass
|
set[str] | None
|
Optional set of paths that skip authentication (e.g. {"/health", "/ready"}). Trailing slashes are ignored when matching, so "/health" will also match "/health/". |
None
|
Example
app = FastAPI() auth = FastAPIAuth() auth.protect_app(app, bypass={"/health"})
@app.get("/") def index(user: User = Depends(auth.get_auth_user)): return {"message": f"Welcome {user.email}!"}
@app.get("/health") def health(): return {"status": "ok"}
Source code in src/cognito_auth/fastapi.py
get_auth_user(request)
Get the authenticated and authorised user for this request.
This method is designed to be used with FastAPI's Depends() for dependency injection.
When using protect_app() (RECOMMENDED), this retrieves the user that was validated by the middleware.
When not using protect_app(), this validates the user on-demand.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
Request
|
FastAPI Request object (automatically injected by Depends) |
required |
Returns:
| Type | Description |
|---|---|
User
|
Authenticated and authorised User |
Raises:
| Type | Description |
|---|---|
HTTPException
|
401 if authentication fails, 403 if unauthorised |
Example
auth.protect_app(app)
@app.get("/protected") def protected_route(user: User = Depends(auth.get_auth_user)): return {"email": user.email}
Source code in src/cognito_auth/fastapi.py
Quick Start
from fastapi import FastAPI, Depends
from cognito_auth import User
from cognito_auth.fastapi import FastAPIAuth
app = FastAPI()
# Auto-loads from environment variables
auth = FastAPIAuth()
auth.protect_app(app, bypass={"/health"}) # Protects entire app except /health!
@app.get("/")
def index(user: User = Depends(auth.get_auth_user)):
return {"message": f"Welcome {user.name}!"}
@app.get("/health")
def health():
return {"status": "ok"}
Configuration
FastAPIAuth inherits from BaseAuth and accepts these parameters:
authoriser(optional): Pre-configured Authoriser instance. If not provided, auto-loads from environment variablesredirect_url(optional): Where to redirect unauthorised users (default: "https://public.gds-idea.io/401.html")region(optional): AWS region (default: "eu-west-2")
from cognito_auth import Authoriser
from cognito_auth.fastapi import FastAPIAuth
# Custom configuration
authoriser = Authoriser.from_lists(allowed_groups=["developers"])
auth = FastAPIAuth(
authoriser=authoriser,
redirect_url="https://myapp.com/unauthorised",
region="us-east-1"
)
Behavior
FastAPIAuth uses dependency injection with Depends(). When authentication or authorisation fails:
- With
protect_app(): Middleware redirects toredirect_urlbefore any route executes. Use thebypassparameter to exclude paths like health checks (e.g.bypass={"/health"}). - Without
protect_app(): Routes withDepends(auth.get_auth_user)raiseHTTPException(401 for auth failure, 403 for unauthorised)
The user is stored in request.state.user, making it efficient to call get_auth_user() multiple times.
Development Mode
Enable dev mode for local development without ALB. See Development Mode for full details.
Complete Example
Protect Entire App (Recommended)
from fastapi import FastAPI, Depends, HTTPException
from cognito_auth import User
from cognito_auth.fastapi import FastAPIAuth
app = FastAPI()
# Initialize and protect entire app
auth = FastAPIAuth()
auth.protect_app(app, bypass={"/health"})
@app.get("/health")
def health():
return {"status": "ok"}
@app.get("/")
def index(user: User = Depends(auth.get_auth_user)):
return {
"message": f"Welcome {user.name}!",
"groups": user.groups,
"is_admin": user.is_admin
}
@app.get("/admin")
def admin_only(user: User = Depends(auth.get_auth_user)):
if not user.is_admin:
raise HTTPException(status_code=403, detail="Admin access required")
return {"message": "Admin panel"}
Protect Specific Routes Only
from fastapi import FastAPI, Depends
from cognito_auth import User
from cognito_auth.fastapi import FastAPIAuth
app = FastAPI()
auth = FastAPIAuth()
# Note: NOT calling protect_app()
@app.get("/public")
def public():
return {"message": "Public endpoint"}
@app.get("/protected")
def protected(user: User = Depends(auth.get_auth_user)):
return {"email": user.email}