Skip to main content

Security and Authentication

FastAPI provides a comprehensive set of tools for implementing security and authentication, located primarily in the fastapi.security package. These tools are built on top of FastAPI's dependency injection system, allowing you to define security requirements as reusable components that can be shared across path operations.

Core Security Architecture

Security in this codebase is implemented through classes that inherit from SecurityBase (found in fastapi.security.base). These classes are designed to be used as dependencies. When a security dependency is included in a path operation, FastAPI:

  1. Extracts Credentials: Automatically looks for credentials in the request (headers, query parameters, or cookies).
  2. Validates Scheme: Ensures the provided credentials match the expected scheme (e.g., checking for the "Bearer" prefix in an Authorization header).
  3. Integrates with OpenAPI: Automatically populates the securitySchemes and security sections of the generated OpenAPI schema, enabling the "Authorize" button in the Swagger UI.

OAuth2 Implementation

The fastapi.security.oauth2 module provides tools for implementing OAuth2 flows. The most common implementation is the Password flow with Bearer tokens.

OAuth2PasswordBearer

The OAuth2PasswordBearer class is used to extract a bearer token from the Authorization header.

from fastapi import Depends, FastAPI
from fastapi.security import OAuth2PasswordBearer

app = FastAPI()

# tokenUrl points to the relative URL where the client sends username/password
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

@app.get("/items/")
async def read_items(token: str = Depends(oauth2_scheme)):
return {"token": token}

When oauth2_scheme is called, it looks for an Authorization header. If the header is missing or doesn't start with Bearer , it raises an HTTPException with a 401 status code (unless auto_error=False is passed to the constructor).

Handling Login Forms

To handle the actual login and token generation, FastAPI provides OAuth2PasswordRequestForm. This class is a dependency that parses the request body for username, password, and optional scope, client_id, and client_secret fields, as required by the OAuth2 specification.

from fastapi import Depends, FastAPI
from fastapi.security import OAuth2PasswordRequestForm

@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
# form_data.username and form_data.password are available here
return {"access_token": form_data.username, "token_type": "bearer"}

For stricter compliance, OAuth2PasswordRequestFormStrict can be used, which enforces that the grant_type field must be exactly "password".

HTTP Authentication

The fastapi.security.http module implements standard HTTP authentication schemes.

HTTP Basic

HTTPBasic extracts credentials from the Authorization header using the Basic scheme. It returns an HTTPBasicCredentials object containing the decoded username and password.

from fastapi.security import HTTPBasic, HTTPBasicCredentials

security = HTTPBasic()

@app.get("/users/me")
def read_current_user(credentials: HTTPBasicCredentials = Depends(security)):
return {"username": credentials.username}

HTTP Bearer

HTTPBearer is similar to OAuth2PasswordBearer but is more generic. It returns an HTTPAuthorizationCredentials object containing the scheme (usually "Bearer") and the credentials (the token).

from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

security = HTTPBearer()

@app.get("/secure-data")
def get_data(credentials: HTTPAuthorizationCredentials = Depends(security)):
return {"token": credentials.credentials}

API Key Authentication

The fastapi.security.api_key module provides three classes for extracting API keys from different parts of the request:

  • APIKeyHeader: Looks for the key in a specific header (e.g., X-API-Key).
  • APIKeyQuery: Looks for the key in a query parameter.
  • APIKeyCookie: Looks for the key in a cookie.
from fastapi.security import APIKeyHeader

api_key_header = APIKeyHeader(name="X-API-Key")

@app.get("/protected")
async def protected_route(api_key: str = Depends(api_key_header)):
return {"api_key": api_key}

Advanced Security and Scopes

FastAPI supports fine-grained permissions using OAuth2 scopes.

Using Security vs Depends

While Depends is used for general dependencies, the Security function is used when you need to define specific scopes required for a dependency.

from fastapi import Security
from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token", scopes={"read": "Read items"})

@app.get("/items/")
async def read_items(token: str = Security(oauth2_scheme, scopes=["read"])):
return {"token": token}

SecurityScopes

The SecurityScopes class allows a dependency to access the full list of scopes required by the current path operation and all its parent dependencies. This is useful for centralized validation logic.

from fastapi.security import SecurityScopes

def get_current_user(security_scopes: SecurityScopes, token: str = Depends(oauth2_scheme)):
# security_scopes.scopes contains ["read"] if called from the example above
for scope in security_scopes.scopes:
# validate scope against user permissions
pass
return {"user": "admin"}

Dependency Caching and Scopes

FastAPI normally caches the results of dependencies within a single request. However, security dependencies are handled specially:

  1. Scope-Aware Caching: If the same security dependency is called multiple times in the same request but with different scopes, FastAPI will re-execute the dependency for each unique set of scopes.
  2. Merging Scopes: When using SecurityScopes, FastAPI merges all scopes declared in the dependency chain for that specific path operation, ensuring the dependency has access to the full set of requirements.

This behavior ensures that a single get_current_user dependency can correctly validate different permission requirements for different endpoints, even if they share the same underlying authentication logic.