Skip to main content

Security Schemes and Authentication

Security in this codebase is implemented through a set of Pydantic models in fastapi/openapi/models.py that strictly follow the OpenAPI 3.0.3 specification. These models define how security requirements—such as API keys, Bearer tokens, and OAuth2 flows—are represented in the generated documentation and validated during request processing.

Core Security Models

All security schemes in this project derive from SecurityBase, which establishes the fundamental structure for any authentication mechanism.

class SecurityBase(BaseModelWithConfig):
type_: SecuritySchemeType = Field(alias="type")
description: str | None = None

The SecuritySchemeType enumeration defines the four supported categories of security:

  • apiKey: Authentication via a key in a header, query parameter, or cookie.
  • http: Standard HTTP authentication schemes (e.g., Basic, Bearer).
  • oauth2: OAuth2 authentication flows.
  • openIdConnect: OpenID Connect discovery.

API Key Authentication

API Key authentication is defined by the APIKey model. It requires specifying the location of the key using the APIKeyIn enum and the name of the parameter.

class APIKeyIn(Enum):
query = "query"
header = "header"
cookie = "cookie"

class APIKey(SecurityBase):
type_: SecuritySchemeType = Field(default=SecuritySchemeType.apiKey, alias="type")
in_: APIKeyIn = Field(alias="in")
name: str

In fastapi/security/api_key.py, these models are used to implement specific security dependencies. For example, APIKeyHeader initializes the APIKey model with location=APIKeyIn.header:

# From fastapi/security/api_key.py
class APIKeyHeader(APIKeyBase):
def __init__(self, *, name: str, ...):
super().__init__(
location=APIKeyIn.header,
name=name,
...
)

HTTP Authentication

HTTP authentication schemes use HTTPBase and its specialized subclass HTTPBearer. These models are found in fastapi/openapi/models.py and are utilized by the security classes in fastapi/security/http.py.

class HTTPBase(SecurityBase):
type_: SecuritySchemeType = Field(default=SecuritySchemeType.http, alias="type")
scheme: str

class HTTPBearer(HTTPBase):
scheme: Literal["bearer"] = "bearer"
bearerFormat: str | None = None

When using HTTPBearer in a route, FastAPI expects an Authorization header. If the scheme is missing or incorrect, it returns a 401 status code. Note that HTTPDigest is also available as a model but is currently a stub in the security implementation, requiring manual subclassing for full logic.

OAuth2 Flows and Configuration

OAuth2 is the most complex security implementation, involving multiple potential "flows." The OAuth2 model contains an OAuthFlows object, which can hold configurations for different grant types.

OAuth2 Model Structure

The hierarchy of models for OAuth2 is as follows:

  1. OAuth2: The top-level security scheme.
  2. OAuthFlows: A container for specific flow types.
  3. OAuthFlow: The base for all flows, containing scopes and an optional refreshUrl.
class OAuthFlows(BaseModelWithConfig):
implicit: OAuthFlowImplicit | None = None
password: OAuthFlowPassword | None = None
clientCredentials: OAuthFlowClientCredentials | None = None
authorizationCode: OAuthFlowAuthorizationCode | None = None

Specific Flow Requirements

Each flow type has specific URL requirements:

  • Password Flow (OAuthFlowPassword): Requires a tokenUrl.
  • Authorization Code Flow (OAuthFlowAuthorizationCode): Requires both authorizationUrl and tokenUrl.
  • Client Credentials Flow (OAuthFlowClientCredentials): Requires a tokenUrl.
  • Implicit Flow (OAuthFlowImplicit): Requires an authorizationUrl.

In fastapi/security/oauth2.py, classes like OAuth2PasswordBearer automatically construct these models:

# From fastapi/security/oauth2.py
flows = OAuthFlowsModel(
password=cast(
Any,
{
"tokenUrl": tokenUrl,
"refreshUrl": refreshUrl,
"scopes": scopes,
},
)
)

OpenID Connect

The OpenIdConnect model provides a way to define an OpenID Connect discovery URL.

class OpenIdConnect(SecurityBase):
type_: SecuritySchemeType = Field(
default=SecuritySchemeType.openIdConnect, alias="type"
)
openIdConnectUrl: str

In the current implementation within fastapi/security/open_id_connect_url.py, this class serves primarily as a metadata provider for OpenAPI. It does not implement the full OIDC validation logic out of the box; developers typically subclass it to add specific validation for their OIDC provider.

Implementation Details

Error Handling and auto_error

Most security classes in fastapi/security accept an auto_error boolean. When True (the default), FastAPI will automatically raise an HTTPException (401 Unauthorized) if the security requirement is not met. If False, the dependency returns None, allowing for optional authentication.

WWW-Authenticate Headers

For compliance with RFC 9110, this codebase ensures that 401 responses include a WWW-Authenticate header.

  • For APIKey schemes, a custom challenge APIKey is used.
  • For HTTPBearer and OAuth2 (by default), the challenge is Bearer.

Security Scopes

The SecurityScopes class in fastapi/security/oauth2.py allows dependencies to access the full list of scopes required by all dependencies in a single request chain. This is useful for complex authorization logic where different parts of a route require different permissions.

class SecurityScopes:
def __init__(self, scopes: list[str] | None = None):
self.scopes = scopes or []
self.scope_str = " ".join(self.scopes)

OAuth2 Request Forms

The codebase provides OAuth2PasswordRequestForm and OAuth2PasswordRequestFormStrict to handle the parsing of form data for the password flow. The "Strict" version enforces that the grant_type must be exactly "password", as required by the OAuth2 specification.