new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

FastAPI · Tutorial · all subjects

security

63 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

Never store plaintext passwords

Never store user passwords in plaintext. Always store a secure hash that can be verified later. Password hashing is covered in the security chapters of the FastAPI tutorial.

HTTPException with detail parameter

When raising an HTTPException, provide a status_code and a detail parameter. The detail parameter can be any JSON-serializable value: a string, dict, list, or other types. FastAPI automatically converts these to JSON in the response.

HTTPException import and basic usage

Import HTTPException from fastapi. To return HTTP error responses to clients, raise an HTTPException (do not return it). Raising an exception will terminate the current path operation immediately and send the HTTP error to the client.

HTTPException for item not found example

Example: raise HTTPException(status_code=404, detail="Item not found") when a requested item by ID does not exist. The client receives HTTP 404 with JSON response {"detail": "Item not found"}.

HTTPException with custom headers

When raising an HTTPException, you can add custom headers using the headers parameter: raise HTTPException(status_code=403, detail="...", headers={"X-Custom-Header": "value"}). This is useful for advanced security scenarios.

Custom exception handlers with @app.exception_handler()

Register custom exception handlers using the @app.exception_handler(ExceptionClass) decorator. The handler function receives Request and the exception instance, and must return a Response. This allows global handling of custom exceptions throughout the application.

Override request validation error handler

To override the default validation error response, create a handler decorated with @app.exception_handler(RequestValidationError). Import RequestValidationError from fastapi.exceptions. The handler receives Request and RequestValidationError exception, and should return a Response with custom formatting.

Override HTTPException error handler

To override the default HTTPException response (e.g., to return plain text instead of JSON), create a handler decorated with @app.exception_handler(HTTPException). The handler receives Request and HTTPException, and should return a custom Response type.

RequestValidationError contains body attribute

The RequestValidationError exception includes a body attribute containing the invalid request data that failed validation. This can be accessed in a custom exception handler to log or return the problematic data to the user for debugging.

FastAPI HTTPException vs Starlette HTTPException difference

FastAPI's HTTPException accepts any JSON-serializable value for the detail field, while Starlette's HTTPException only accepts strings. FastAPI's HTTPException inherits from Starlette's. When registering exception handlers, register for Starlette's HTTPException to catch both Starlette internal errors and extensions.

Reuse FastAPI default exception handlers

Import default exception handlers from fastapi.exception_handlers to reuse them alongside custom exception handling logic. This allows you to add custom processing (like logging) while keeping the standard FastAPI error response format.

HTTP status codes for errors: 400-499 range

When reporting errors to a client via an API, return an HTTP status code in the range of 400 to 499. These status codes indicate an error from the client, similar to how 200-299 status codes indicate success.

Custom exception handler with Starlette imports

When creating custom exception handlers, import Request from starlette.requests and Response types from starlette.responses (or use fastapi.responses which re-exports them). For example: from starlette.responses import JSONResponse or PlainTextResponse.

python-multipart dependency for OAuth2

OAuth2 uses form data to send the username and password. The python-multipart package is required for form data handling. When installing FastAPI with uv add "fastapi[standard]", python-multipart is automatically included. If installing with uv add fastapi (without [standard]), python-multipart is not included by default and must be installed manually with uv add python-multipart.

OAuth2 password flow overview

The OAuth2 password flow is a security flow where: (1) the user types username and password in the frontend and hits Enter, (2) the frontend sends username and password to a specific URL in the API (declared with tokenUrl parameter), (3) the API checks the credentials and responds with a token string, (4) the frontend stores the token temporarily, (5) when the frontend needs authenticated access, it sends an Authorization header with value Bearer plus the token. A token is set to expire after some time so the user must log in again later, limiting the risk if the token is stolen.

OAuth2PasswordBearer class and tokenUrl parameter

FastAPI provides the OAuth2PasswordBearer class to implement OAuth2 password flow with Bearer tokens. When creating an instance, pass the tokenUrl parameter containing the URL that the client will use to get a token. The tokenUrl parameter should use a relative URL (e.g., tokenUrl="token" refers to ./token). If the API is at https://example.com/, a relative URL tokenUrl="token" refers to https://example.com/token. If the API is at https://example.com/api/v1/, the same relative URL refers to https://example.com/api/v1/token. Using relative URLs ensures the application works correctly behind a proxy. The tokenUrl parameter does not create the endpoint but declares which URL the client should use; this information is used in OpenAPI and interactive API documentation.

OAuth2PasswordBearer as a dependency

An instance of OAuth2PasswordBearer is callable and can be used with Depends as a dependency. When passed to a path operation function via Depends, it provides a str parameter containing the token extracted from the request.

OAuth2PasswordBearer checks Authorization header

OAuth2PasswordBearer looks in the request for an Authorization header, checks if the value is Bearer plus some token, and returns the token as a str. If the Authorization header is missing or does not have a Bearer token, it responds with a 401 UNAUTHORIZED status code directly. If the path operation function is executed, it is guaranteed to have a str value for the token.

Security scheme inheritance in OpenAPI

FastAPI recognizes security classes that inherit from fastapi.security.base.SecurityBase and uses them to define security schemes in the OpenAPI schema and automatic API documentation. OAuth2PasswordBearer inherits from fastapi.security.oauth2.OAuth2, which inherits from fastapi.security.base.SecurityBase, enabling FastAPI to integrate it with OpenAPI.

Bearer token format in Authorization header

When authenticating with a Bearer token, the Authorization header value takes the format: Bearer followed by a space and then the token. For example, if the token is "foobar", the Authorization header value is "Bearer foobar".

Relative URL importance for tokenUrl

Using a relative URL for tokenUrl is important to ensure the application works correctly in advanced use cases like when the API is behind a proxy. Relative URLs automatically adjust based on the API's actual location.

Use utility function to resolve token to user

In get_current_user, use a utility function that takes a token string as input and returns the corresponding User Pydantic model instance.

FastAPI security is flexible with data models

The dependency injection security system in FastAPI works with any data model, class, or type: Pydantic models, plain strings, dictionaries, database model instances, or custom classes. You can use different dependencies that all return the same type or different types.

Security and dependencies are reusable across endpoints

Write security and dependency injection logic once in a single place. Thousands of path operations can then reuse these same dependencies, keeping individual endpoint code as small as 3 lines.

Create a Pydantic user model for security

Use a Pydantic model to represent the User entity in security systems, the same way you declare request bodies. This provides type hints and validation.

Create get_current_user dependency with sub-dependency

Create a dependency function called get_current_user that has a sub-dependency. The sub-dependency (such as oauth2_scheme) provides a token string, which get_current_user receives and uses to return a User model.

Inject current user into path operation with Depends

Declare the current_user parameter in a path operation function using Depends(get_current_user). Declare the type of current_user as the Pydantic User model. This provides type hints and code completion while avoiding confusion with request bodies.

OpenID Connect specification

OpenID Connect is a specification based on OAuth2 that extends OAuth2 by specifying things that are relatively ambiguous in OAuth2 to make it more interoperable. For example, Google login uses OpenID Connect underneath, while Facebook login uses its own flavor of OAuth2.

OAuth2 specification overview

OAuth2 is a specification that defines several ways to handle authentication and authorization. It covers several complex use cases and includes ways to authenticate using third parties, such as Facebook, Google, X (Twitter), and GitHub login systems. OAuth2 does not specify how to encrypt communication and expects the application to be served with HTTPS.

OAuth 1 vs OAuth2

OAuth 1 existed before OAuth2 and was more complex because it included direct specifications on how to encrypt communication. OAuth 1 is not very popular or used nowadays. OAuth2 is the current standard.

OpenID (legacy specification)

OpenID is a legacy specification that tried to solve the same problem as OpenID Connect but was not based on OAuth2. It was a complete separate system and is not very popular or used nowadays.

OpenAPI security schemes

OpenAPI defines the following security schemes: apiKey (can come from a query parameter, header, or cookie), http (standard HTTP authentication including bearer with Authorization header, HTTP Basic authentication, HTTP Digest), oauth2 (all OAuth2 flows including implicit, clientCredentials, authorizationCode for building authentication providers, and password flow for handling authentication in the same application), and openIdConnect (has a way to define how to discover OAuth2 authentication data automatically as defined in the OpenID Connect specification).

FastAPI security module

FastAPI provides several tools for security schemes in the fastapi.security module that simplify using security mechanisms. These tools can be used to add security to APIs and are automatically integrated into the interactive documentation system.

FastAPI based on OpenAPI

FastAPI is based on OpenAPI (previously known as Swagger), which is the open specification for building APIs. This is what makes it possible to have multiple automatic interactive documentation interfaces and code generation.

Timing attack prevention in authentication

When authenticate_user is called with a username that does not exist in the database, verify_password should still run against a dummy hash. This ensures the endpoint takes roughly the same amount of time to respond whether the username is valid or not, preventing timing attacks that could enumerate existing usernames.

JWT Secret Key generation

Generate a secure random secret key using the command `openssl rand -hex 32`. Copy the output to the variable `SECRET_KEY` and do not use example keys in production.

JWT signing algorithm and token expiration setup

Create a variable `ALGORITHM` set to the string "HS256" for the algorithm used to sign JWT tokens. Create a variable for the expiration time of the token.

JWT token endpoint response model

Define a Pydantic Model that will be used in the token endpoint for the response. Create a utility function to generate a new access token.

JWT get_current_user dependency

Update get_current_user to receive the same token as before, but using JWT tokens. Decode the received token, verify it, and return the current user. If the token is invalid, return an HTTP error right away.

JWT token endpoint implementation

In the /token path operation, create a timedelta with the expiration time of the token. Create a real JWT access token and return it.

JWT subject (sub) claim specification

The JWT specification defines a key 'sub' for the subject of the token. It is optional to use, but is where you put the user's identification. The 'sub' key should have a unique identifier across the entire application and should be a string.

JWT subject (sub) for non-user entities

JWT can be used for identifying entities other than users, such as a car or blog post. You can add permissions about that entity (like 'drive' for a car or 'edit' for a blog post) and give that JWT token to a user or bot without requiring them to have an account. To avoid ID collisions when multiple entities share the same ID, prefix the 'sub' value with a type identifier (for example, 'username:johndoe' for a user).

Authorization header format with Bearer tokens

The Authorization header should include a value that starts with 'Bearer ' followed by the token. This is the standard format for transmitting JWT tokens in HTTP requests.

JWT structure and content

JWT means JSON Web Tokens. It is a standard to codify a JSON object in a long dense string without spaces. It is not encrypted, so anyone could recover the information from the contents. However, it is signed, so when you receive a token that you issued, you can verify that it was you who issued it.

OAuth2 scopes in FastAPI

OAuth2 has the notion of scopes. You can use them to add a specific set of permissions to a JWT token. You can give this token to a user or third party to interact with your API with a set of restrictions. OAuth2 with scopes is the mechanism used by many big authentication providers like Facebook, Google, GitHub, Microsoft, and X (Twitter).

FastAPI security flexibility

FastAPI does not make compromise with any database, data model or tool. It gives all the flexibility to choose the ones that fit the project best. You can use directly many well maintained and widely used packages like pwdlib and PyJWT because FastAPI does not require complex mechanisms to integrate external packages.

JWT token expiration and verification

You can create a token with an expiration of a specified time period (such as one week). When the user returns with the token, you can verify it was issued by you. After expiration, the token becomes invalid and the user must sign in again. If someone tries to modify the token to change the expiration, the signature would not match and the modification would be discovered.

Install PyJWT for JWT tokens

Install PyJWT using the command `uv add pyjwt`. If planning to use digital signature algorithms like RSA or ECDSA, install the cryptography library dependency with `uv add pyjwt[crypto]`.

Why use password hashing

If a database is stolen, the thief will not have users' plaintext passwords, only the hashes. This prevents the thief from trying to use that password in another system, which is important since many users use the same password everywhere.

Install pwdlib for password hashing

Install pwdlib with Argon2 using the command `uv add "pwdlib[argon2]"`. The recommended algorithm is Argon2. pwdlib supports many secure hashing algorithms and can read passwords created by other frameworks like Django or Flask.

Not authenticated error response

When a user is not authenticated or lacks a valid token, the endpoint should return an HTTP 401 status with a JSON error response containing detail 'Not authenticated'.

OAuth2PasswordRequestForm fields

OAuth2PasswordRequestForm is a class dependency that declares a form body with the following fields: username (required), password (required), scope (optional, a single string with scopes separated by spaces), grant_type (optional), client_id (optional), and client_secret (optional). The instance has a scopes attribute containing the actual list of strings for each scope sent, not a scope attribute.

OAuth2PasswordRequestFormStrict enforces grant_type

If you need to enforce that the grant_type field has a fixed value of 'password' as required by the OAuth2 spec, use OAuth2PasswordRequestFormStrict instead of OAuth2PasswordRequestForm.

OAuth2 password flow form field requirements

When using the OAuth2 password flow, the client must send username and password fields as form data (not JSON). The field names must be exactly 'username' and 'password' to be compatible with the OAuth2 specification. These field names are required for compatibility with integrated API documentation systems.

OAuth2 scope definition

In OAuth2, a scope is a string that declares a specific permission required. The client can send a scope form field containing a long string with multiple scopes separated by spaces. Each scope is a string without spaces. Common examples include 'users:read', 'users:write', 'instagram_basic', or 'https://www.googleapis.com/auth/drive'. Scopes are just strings and can contain various characters like colons or URLs—the format details are implementation-specific.

Token endpoint response format

The token endpoint response must be a JSON object containing an access_token field with a string value and a token_type field. For bearer tokens, the token_type value should be 'bearer'. This is a specification requirement that must be implemented correctly in your code.

WWW-Authenticate header with Bearer tokens

When returning an HTTP 401 'UNAUTHORIZED' status code for bearer token authentication, include a WWW-Authenticate header with the value 'Bearer'. While this header is not strictly required for the endpoint to work, it is part of the specification and may be expected by tools and clients that follow the standard.

Dependency chain for authenticated active users

To ensure a user is both authenticated and active, create a dependency chain where get_current_active_user depends on get_current_user. The get_current_active_user dependency will check if the user is active and return an HTTP error if the user doesn't exist or is inactive. This pattern ensures endpoints only receive valid, active users.

Password hashing concept

Password hashing converts content into a sequence of bytes that looks like gibberish. When you pass the exact same password, you get the exact same hash. However, you cannot convert the hash back to the original password. This is important because if a database is stolen, attackers will only have hashes, not plaintext passwords, preventing them from using those passwords in other systems.

Python dictionary unpacking with **

The expression UserInDB(**user_dict) unpacks the dictionary keys and values as keyword arguments. For example, UserInDB(**{'username': 'john', 'email': 'john@example.com', 'full_name': 'John Doe', 'disabled': False, 'hashed_password': 'hash'}) is equivalent to UserInDB(username='john', email='john@example.com', full_name='John Doe', disabled=False, hashed_password='hash').

Give your agent this brain