presentation.routers.api.middleware.auth_dependencies¶
src.presentation.routers.api.middleware.auth_dependencies
¶
JWT authentication dependencies.
FastAPI dependencies for extracting and validating JWT tokens. Use these dependencies to protect routes that require authentication.
Usage
Protected route (requires auth)¶
@router.get("/protected") async def protected_route( current_user: CurrentUser = Depends(get_current_user), ): return {"user_id": str(current_user.user_id)}
Optional auth route¶
@router.get("/optional") async def optional_route( current_user: CurrentUser | None = Depends(get_current_user_optional), ): if current_user: return {"user_id": str(current_user.user_id)} return {"message": "anonymous"}
Classes¶
CurrentUser
dataclass
¶
Authenticated user information from JWT.
Immutable dataclass containing user identity extracted from JWT token. Available as a dependency in protected routes.
Attributes:
| Name | Type | Description |
|---|---|---|
user_id |
UUID
|
User's unique identifier (from JWT 'sub' claim). |
email |
str
|
User's email address (from JWT 'email' claim). |
roles |
list[str]
|
User's roles (from JWT 'roles' claim). |
session_id |
UUID | None
|
Session ID if present (from JWT 'session_id' claim). |
token_jti |
str | None
|
JWT unique identifier (for token tracking/revocation checks). |
Source code in src/presentation/routers/api/middleware/auth_dependencies.py
Functions¶
get_current_user
async
¶
get_current_user(
credentials: Annotated[
HTTPAuthorizationCredentials, Depends(bearer_scheme)
],
token_service: Annotated[
TokenGenerationProtocol, Depends(get_token_service)
],
) -> CurrentUser
Get current authenticated user from JWT token.
FastAPI dependency that extracts and validates the JWT access token from the Authorization header and returns the user information.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
credentials
|
Annotated[HTTPAuthorizationCredentials, Depends(bearer_scheme)]
|
Bearer token from Authorization header. |
required |
token_service
|
Annotated[TokenGenerationProtocol, Depends(get_token_service)]
|
JWT token service (injected). |
required |
Returns:
| Type | Description |
|---|---|
CurrentUser
|
CurrentUser with user identity from valid JWT. |
Raises:
| Type | Description |
|---|---|
HTTPException 401
|
If token is missing, invalid, or expired. |
Usage
@router.get("/protected") async def protected_route( current_user: CurrentUser = Depends(get_current_user), ): return {"user_id": str(current_user.user_id)}
Source code in src/presentation/routers/api/middleware/auth_dependencies.py
get_current_user_optional
async
¶
get_current_user_optional(
credentials: Annotated[
HTTPAuthorizationCredentials | None,
Depends(bearer_scheme_optional),
],
token_service: Annotated[
TokenGenerationProtocol, Depends(get_token_service)
],
) -> CurrentUser | None
Get current user if authenticated, None otherwise.
FastAPI dependency for routes that work with or without authentication. Does not raise errors for missing or invalid tokens.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
credentials
|
Annotated[HTTPAuthorizationCredentials | None, Depends(bearer_scheme_optional)]
|
Optional Bearer token from Authorization header. |
required |
token_service
|
Annotated[TokenGenerationProtocol, Depends(get_token_service)]
|
JWT token service (injected). |
required |
Returns:
| Type | Description |
|---|---|
CurrentUser | None
|
CurrentUser if valid token provided, None otherwise. |
Usage
@router.get("/public-or-private") async def route( current_user: CurrentUser | None = Depends(get_current_user_optional), ): if current_user: return {"message": f"Hello, {current_user.email}"} return {"message": "Hello, anonymous"}
Source code in src/presentation/routers/api/middleware/auth_dependencies.py
get_current_active_user
async
¶
get_current_active_user(
current_user: Annotated[
CurrentUser, Depends(get_current_user)
],
cache: Annotated[CacheProtocol, Depends(get_cache)],
session: Annotated[
AsyncSession, Depends(get_db_session)
],
) -> CurrentUser
Get current user with session revocation check.
Security Layer: Verifies JWT is valid AND session is not revoked. This prevents post-logout token reuse attacks.
Flow
- JWT already validated (by get_current_user dependency)
- Extract session_id from JWT payload
- Check session in Redis cache (fast path <5ms)
- If cache miss, check database (slow path ~50ms)
- Verify session exists and is NOT revoked
- Return 401 if session revoked
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
current_user
|
Annotated[CurrentUser, Depends(get_current_user)]
|
Current user from JWT (already validated). |
required |
cache
|
Annotated[CacheProtocol, Depends(get_cache)]
|
Redis cache for fast session lookups. |
required |
session
|
Annotated[AsyncSession, Depends(get_db_session)]
|
Database session for fallback lookups. |
required |
Returns:
| Type | Description |
|---|---|
CurrentUser
|
CurrentUser if session is valid and not revoked. |
Raises:
| Type | Description |
|---|---|
HTTPException 401
|
If session is revoked or not found. |
Security
- Prevents token reuse after logout
- Prevents token reuse after password change
- Prevents token reuse after manual session revocation
Reference
- F6.5 Security Audit Item 2: JWT/Refresh Token Security
- docs/architecture/session-management-architecture.md
Source code in src/presentation/routers/api/middleware/auth_dependencies.py
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | |
require_role
¶
Create a dependency that requires a specific role.
Factory function that creates a dependency checking for specific role.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
required_role
|
str
|
Role required to access the endpoint. |
required |
Returns:
| Type | Description |
|---|---|
Callable[..., Awaitable[CurrentUser]]
|
Dependency function that validates user has required role. |
Usage
@router.delete("/admin/users/{id}") async def delete_user( user_id: UUID, current_user: CurrentUser = Depends(require_role("admin")), ): # Only admins can reach here ...
Raises:
| Type | Description |
|---|---|
HTTPException 403
|
If user does not have required role. |
Source code in src/presentation/routers/api/middleware/auth_dependencies.py
require_any_role
¶
Create a dependency that requires any of the specified roles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*required_roles
|
str
|
Roles where user must have at least one. |
()
|
Returns:
| Type | Description |
|---|---|
Callable[..., Awaitable[CurrentUser]]
|
Dependency function that validates user has at least one role. |
Usage
@router.get("/dashboard") async def dashboard( current_user: CurrentUser = Depends(require_any_role("admin", "manager")), ): # Admins and managers can access ...