| name | fastapi-auth-patterns |
| description | Implement and validate FastAPI authentication strategies including JWT tokens, OAuth2 password flows, OAuth2 scopes for permissions, and Supabase integration. Use when implementing authentication, securing endpoints, handling user login/signup, managing permissions, integrating OAuth providers, or when user mentions JWT, OAuth2, Supabase auth, protected routes, access control, role-based permissions, or authentication errors. |
| allowed-tools | Read, Grep, Glob, Bash, Write, Edit |
FastAPI Authentication Patterns
Purpose: Autonomously implement, validate, and debug FastAPI authentication systems with multiple strategies.
Activation Triggers:
- Implementing user authentication
- Securing API endpoints
- JWT token generation/validation issues
- OAuth2 flow configuration
- Permission and role-based access control
- Supabase authentication integration
- Authentication errors (401, 403)
- Password hashing and security
Key Resources:
scripts/setup-jwt.sh- Initialize JWT authentication systemscripts/validate-auth.sh- Validate authentication configurationtemplates/jwt_auth.py- Complete JWT authentication implementationtemplates/oauth2_flow.py- OAuth2 password flow with scopestemplates/supabase_auth.py- Supabase integration for FastAPIexamples/protected_routes.py- Protected endpoint patternsexamples/permission_system.py- Role and permission-based access
Authentication Strategies
1. JWT Token Authentication
Use When:
- Need stateless authentication
- Building API for mobile/web clients
- Require token expiration control
- Implementing refresh token patterns
Setup:
./scripts/setup-jwt.sh
Core Components:
- Password hashing with Argon2 (pwdlib)
- JWT token generation with expiration
- Token validation and user extraction
- Secure secret key management
Implementation Pattern:
# Hash passwords (never store plaintext)
password_hash = PasswordHash.recommended()
hashed = password_hash.hash(plain_password)
# Generate JWT token
def create_access_token(data: dict, expires_delta: timedelta):
to_encode = data.copy()
expire = datetime.now(timezone.utc) + expires_delta
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm="HS256")
# Validate token and extract user
async def get_current_user(token: str = Depends(oauth2_scheme)):
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
username = payload.get("sub")
return get_user(username)
Key Points:
- Use environment variables for SECRET_KEY
- Default token expiration: 30 minutes
- Store username in "sub" claim
- Validate token signature and expiration
2. OAuth2 Password Flow
Use When:
- Building first-party applications
- Need username/password authentication
- Following OAuth2 standards
- Integrating with OpenAPI documentation
Template: templates/oauth2_flow.py
Flow:
- User submits credentials via
OAuth2PasswordRequestForm - Server verifies password hash
- Server returns signed JWT access token
- Client includes token in Authorization header
Security Scheme:
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(form_data.username, form_data.password)
access_token = create_access_token(data={"sub": user.username})
return {"access_token": access_token, "token_type": "bearer"}
3. OAuth2 Scopes (Permissions)
Use When:
- Need fine-grained permission control
- Implementing role-based access
- Building multi-tenant systems
- Following least-privilege principle
Template: See templates/oauth2_flow.py (includes scopes)
Define Scopes:
oauth2_scheme = OAuth2PasswordBearer(
tokenUrl="token",
scopes={
"me": "Read information about current user",
"items": "Read items",
"items:write": "Create and modify items"
}
)
Encode Scopes in Token:
# During login, add user's scopes to token
token_data = {"sub": username, "scopes": user.scopes}
access_token = create_access_token(token_data)
Protect Endpoints with Scopes:
async def get_current_user(
security_scopes: SecurityScopes,
token: str = Depends(oauth2_scheme)
):
# Validate token has required scopes
for scope in security_scopes.scopes:
if scope not in token_data.scopes:
raise HTTPException(401, "Not enough permissions")
@app.get("/users/me/items/")
async def read_items(
current_user: User = Security(get_current_active_user, scopes=["items"])
):
return current_user.items
4. Supabase Authentication
Use When:
- Using Supabase as backend
- Need managed authentication service
- Want OAuth providers (Google, GitHub, etc.)
- Require user management dashboard
Template: templates/supabase_auth.py
Setup:
from supabase import create_client, Client
supabase: Client = create_client(
os.getenv("SUPABASE_URL"),
os.getenv("SUPABASE_KEY")
)
Sign Up:
# Email/password signup
response = supabase.auth.sign_up({
"email": "user@example.com",
"password": "secure_password",
"options": {"data": {"full_name": "John Doe"}}
})
Sign In:
response = supabase.auth.sign_in_with_password({
"email": "user@example.com",
"password": "secure_password"
})
access_token = response.session.access_token
Validate Token in FastAPI:
async def get_current_user(token: str = Depends(oauth2_scheme)):
# Validate Supabase JWT token
user = supabase.auth.get_user(token)
return user
Integration Pattern:
- Store Supabase session in HTTP-only cookies (server-side)
- Use PKCE flow for OAuth providers
- Implement token refresh logic
- Leverage Supabase RLS policies for data access
Validation Workflow
1. Run Authentication Validator
./scripts/validate-auth.sh
Checks Performed:
- ✅ Required packages installed (fastapi, python-jose[cryptography], passlib[argon2], pwdlib)
- ✅ Environment variables set (SECRET_KEY, ALGORITHM, ACCESS_TOKEN_EXPIRE_MINUTES)
- ✅ Security scheme configured correctly
- ✅ Password hashing implemented
- ✅ Token generation and validation functions present
- ✅ Protected endpoints use proper dependencies
2. Common Issues & Fixes
Missing SECRET_KEY:
# Generate secure random key
openssl rand -hex 32
# Add to .env
echo 'SECRET_KEY=your_generated_key' >> .env
Token Expired (401):
- Increase ACCESS_TOKEN_EXPIRE_MINUTES
- Implement refresh token pattern
- Check server/client time sync
Invalid Credentials:
- Verify password hashing algorithm matches
- Check user exists in database
- Validate password comparison logic
Missing Permissions (403):
- Verify user has required scopes
- Check scope encoding in token
- Validate SecurityScopes configuration
Supabase Connection Failed:
- Verify SUPABASE_URL and SUPABASE_KEY
- Check project settings in Supabase dashboard
- Validate network connectivity
Protected Routes Pattern
Example: examples/protected_routes.py
# Public endpoint (no auth)
@app.get("/")
async def root():
return {"message": "Public endpoint"}
# Protected endpoint (requires authentication)
@app.get("/users/me")
async def read_users_me(current_user: User = Depends(get_current_user)):
return current_user
# Protected with specific permission
@app.post("/items/")
async def create_item(
item: Item,
current_user: User = Security(get_current_active_user, scopes=["items:write"])
):
return create_item_for_user(current_user, item)
# Admin-only endpoint
@app.delete("/users/{user_id}")
async def delete_user(
user_id: int,
current_user: User = Depends(get_current_admin_user)
):
return delete_user_by_id(user_id)
Permission System Pattern
Example: examples/permission_system.py
Role-Based Access Control (RBAC):
class Role(str, Enum):
ADMIN = "admin"
USER = "user"
GUEST = "guest"
class User(BaseModel):
username: str
role: Role
permissions: List[str]
def has_permission(user: User, required_permission: str) -> bool:
# Admins have all permissions
if user.role == Role.ADMIN:
return True
return required_permission in user.permissions
async def require_permission(permission: str):
async def permission_checker(current_user: User = Depends(get_current_user)):
if not has_permission(current_user, permission):
raise HTTPException(403, f"Permission '{permission}' required")
return current_user
return permission_checker
# Usage
@app.delete("/items/{item_id}")
async def delete_item(
item_id: int,
current_user: User = Depends(require_permission("items:delete"))
):
return delete_item_by_id(item_id)
Best Practices
Security:
- Never store passwords in plaintext
- Use Argon2 for password hashing (recommended over bcrypt)
- Store SECRET_KEY in environment variables (never commit)
- Use HTTPS in production
- Implement rate limiting on login endpoints
- Add token refresh mechanism for long sessions
Token Management:
- Short access token expiration (15-30 minutes)
- Long refresh token expiration (7-30 days)
- Rotate refresh tokens on use
- Implement token revocation list for logout
Scope Design:
- Use hierarchical scopes (e.g., items, items:read, items:write)
- Follow least-privilege principle
- Document all scopes in OpenAPI
- Validate scopes on every request
Error Handling:
- Return 401 for authentication failures
- Return 403 for authorization failures
- Include WWW-Authenticate header with 401
- Log authentication attempts for security monitoring
Dependencies
Required Packages:
pip install fastapi
pip install python-jose[cryptography]
pip install pwdlib[argon2]
pip install supabase # If using Supabase
Environment Variables:
SECRET_KEY=your_secret_key_here
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
# For Supabase
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your_anon_key
Supported Auth Strategies: JWT, OAuth2 Password Flow, OAuth2 Scopes, Supabase
Version: 1.0.0 FastAPI Compatibility: 0.100+