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 · all subjects

security & oauth2

55 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

OAuth2 scopes are space-separated strings in spec

The OAuth2 specification defines scopes as a list of space-separated strings. Each string can be in any format but must not contain spaces. Scopes represent permissions and are only strings to OAuth2 — the format (like 'users:read', 'instagram_basic', or 'https://www.googleapis.com/auth/drive') is implementation-specific.

Declare OAuth2 security scheme with scopes parameter

The OAuth2 security schema is declared with a 'scopes' parameter that receives a dict where each scope is a key and its description is the value. This makes the scopes appear in the API documentation, allowing users to select which scopes they want to authorize when logging in.

Use Security to declare scopes in path operations

Import and use 'Security' from fastapi to declare dependencies with scope requirements in path operations. Security works like Depends but also accepts a 'scopes' parameter containing a list of scope strings. Security is actually a subclass of Depends with an additional parameter for scopes.

SecurityScopes parameter type captures required scopes

Declare a parameter of type 'SecurityScopes' (imported from 'fastapi.security') in a dependency function. The SecurityScopes object has two key attributes: 'scopes' (a list containing all scopes required by the current function and its dependants across the dependency tree) and 'scope_str' (a single space-separated string of all scopes).

SecurityScopes scope_str for WWW-Authenticate header

The 'scope_str' attribute of a SecurityScopes object provides a space-separated string of all required scopes. This string is used in the 'WWW-Authenticate' header when raising HTTPException for scope validation failures.

Pydantic TokenData model must include scopes field

Update the Pydantic TokenData model with a 'scopes' attribute to validate JWT token data. This ensures the token contains a list of strings for scopes and a string for username, catching malformed data early and preventing later security issues.

Scope validation checks token contains required scopes

After extracting and validating the token, verify that the token's scopes include all scopes in 'security_scopes.scopes'. Raise HTTPException if any required scope is missing.

SecurityScopes aggregates scopes from entire dependency tree

The 'security_scopes.scopes' parameter in a dependency function contains all scopes declared in that function, its parent dependency functions, and the path operation for the specific request. Each path operation gets a different list of scopes based on the Security declarations in its dependency tree.

Security with scopes in decorator dependencies

You can use Security with scopes in the 'dependencies' parameter of path operation decorators (such as @app.get()), the same way you use Depends. This allows declaring scope requirements at the decorator level.

OAuth2 password flow for trusted first-party authentication

The OAuth2 password flow is appropriate when users log into their own application with a frontend you control, because you can trust receiving the username and password. It is not suitable for third-party integrations.

OAuth2 implicit and authorization code flows for third parties

When creating an OAuth2 application that third parties would connect to (acting as an authentication provider like Facebook or Google), use OAuth2 flows other than the password flow. The implicit flow is most common; the authorization code flow is most secure but has more complex implementation with additional steps.

Only add user-permitted scopes to JWT token

For security reasons, ensure that only scopes the user actually has or scopes you have predefined are added to the JWT token. Do not automatically add all requested scopes without validation.

Use Depends for dependencies without scope requirements

If a dependency function has no scope requirements itself, use Depends (not Security) to declare it. Security is only necessary when declaring scope requirements.

Bearer token in Authorization header

When sending a JWT token in requests, use the Authorization header with a value beginning with 'Bearer ' followed by the token. For example: Authorization: Bearer <token>.

FastAPI security design philosophy

FastAPI does not make compromises with any database, data model, or tool for security implementation. It gives you full flexibility to choose those that best fit your project. You can directly use well-maintained and widely-used packages like pwdlib and PyJWT because FastAPI does not require complex mechanisms to integrate external packages. FastAPI provides tools to simplify the process without compromising flexibility, robustness, or security, and allows secure standard protocols like OAuth2 to be implemented in a relatively simple way.

Error message for authentication failure

When username or password validation fails in OAuth2 authentication, return the error message 'Incorrect username or password' using HTTPException. When a user is inactive, return the error message 'Inactive user'.

OAuth2 scopes definition in OpenAPI

OAuth2 scopes are declared as a dict with the scopes parameter, where each scope is a key and its description is the value. The scopes parameter is passed to the OAuth2PasswordBearer or similar security scheme declaration. These scopes will appear in the API docs when users authorize.

Security vs Depends for scope requirements

Security is a subclass of Depends that accepts an additional scopes parameter for declaring security scope requirements. Use Security instead of Depends when you need to declare security scopes. Security is imported from fastapi.

SecurityScopes class and its properties

SecurityScopes is a class imported from fastapi.security that can be declared as a parameter in dependency functions. It has a scopes property containing a list of all scopes required by the current dependency and all dependants (parent dependencies). It also has a scope_str attribute that returns the scopes as a single space-separated string.

OAuth2PasswordRequestForm with scopes

OAuth2PasswordRequestForm includes a scopes property which is a list of str containing each scope received in the request. These scopes can be returned as part of the JWT token.

Scope format in OAuth2

In OAuth2, a scope is a string that should not contain spaces. The content can have any format, including characters like colons or URLs (e.g., users:read, instagram_basic, https://www.googleapis.com/auth/drive). These strings represent specific permissions.

Declaring scopes in path operations with Security

Use Security() with a dependency function and a scopes parameter (list of strings) to declare scope requirements at the path operation level. Example: Security(get_current_active_user, scopes=['items']). The scopes are collected through the dependency tree and made available to all dependencies.

Scope requirements through dependency tree

When a path operation declares Security with scopes and that depends on another function that also declares Security with scopes, the SecurityScopes parameter in the lowest dependency will contain all scopes from the entire dependency tree for that specific path operation.

TokenData model with scopes property

The Pydantic TokenData model used to validate JWT token data should include a scopes property of type list to store the scopes included in the token. This ensures validation that scopes are exactly a list of strings and not other types.

Verifying token scopes against requirements

After extracting and validating scopes from a JWT token, verify that all scopes in security_scopes.scopes (required scopes) are included in the scopes from the token. Raise an HTTPException if required scopes are missing. Include the required scopes as a space-separated string in the WWW-Authenticate header.

SecurityScopes available at any dependency level

SecurityScopes can be declared and used at any point in the dependency tree, not just at the root. Each SecurityScopes instance will contain only the scopes required for that specific path operation and its specific dependency tree, allowing verification in a central dependency and different scope requirements in different path operations.

OAuth2 password flow for own applications

The OAuth2 password flow is appropriate for applications logging into their own service with their own frontend, since the frontend is trusted to receive username and password. For third-party authentication providers (equivalent to Facebook, Google, GitHub), use other flows like implicit or code flow.

Security in decorator dependencies parameter

Security can be used in the dependencies parameter of path operation decorators, the same way Depends can be used, allowing declaration of scope requirements at the decorator level.

JWT structure and not encrypted but signed

JWT (JSON Web Tokens) is a standard to codify a JSON object in a long dense string without spaces. JWT is not encrypted, so anyone could recover the information from the contents. However, JWT is signed, allowing verification that the issuer issued the token. A token can be created with an expiration time (for example, 1 week). If a token is modified to change the expiration, the signature will not match and the modification can be detected.

Purpose of password hashing in FastAPI security

Password hashing converts a password into a sequence of bytes that looks like gibberish. The same password always produces the same hash, but the hash cannot be converted back to the plaintext password. If a database is stolen, the thief will only have the hashes, not the plaintext passwords, preventing them from using the password in other systems where users may have reused the same password.

Install PyJWT for JWT token handling

PyJWT is required to generate and verify JWT tokens in Python. Install it using `uv add pyjwt`. For digital signature algorithms like RSA or ECDSA, install the cryptography dependency with `pyjwt[crypto]`.

Install pwdlib for password hashing

pwdlib is a Python package to handle password hashes. It supports many secure hashing algorithms. The recommended algorithm is Argon2. Install it using `uv add "pwdlib[argon2]"`.

Timing attack prevention with verify_password

When authenticate_user is called with a username that doesn't exist in the database, verify_password is 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 be used to enumerate existing usernames.

Generate secure secret key for JWT signing

A random secret key is used to sign JWT tokens. To generate a secure random secret key, use the command `openssl rand -hex 32`. Copy the output to the variable SECRET_KEY (do not use example values).

HS256 algorithm for JWT signing

Set the ALGORITHM variable to "HS256" for signing JWT tokens.

JWT subject claim 'sub' for user identification

The JWT specification includes a key 'sub' (subject) where the user's identification is stored. The 'sub' key should have a unique identifier across the entire application and should be a string. When using JWT for multiple entity types (users, cars, blog posts), consider prefixing the value to avoid ID collisions, for example: "username:johndoe".

Authorization header Bearer token format

The Authorization header value starts with "Bearer " followed by the JWT token.

OAuth2 scopes for permissions

OAuth2 has the notion of scopes, which can be used to add a specific set of permissions to a JWT token. Scopes allow restrictions on token usage when giving a token to a user or third party to interact with the API. OAuth2 with scopes is the mechanism used by Facebook, Google, GitHub, Microsoft, X (Twitter), and other major authentication providers to authorize third party applications.

Password hashing prevents plain text storage

When authenticating users, the plaintext password is only sent in the initial request to authenticate and get an access token. The plaintext password is not stored in the database or sent in subsequent requests; only the hashed version is stored.

OAuth2 password flow username and password field names

In OAuth2 password flow, the client must send username and password as form data. The fields must be named exactly 'username' and 'password' to comply with the spec. Alternative names like 'user-name' or 'email' will not work for the login path operation, though you can display different names to end users in the frontend and use different names in database models.

OAuth2 scope field format

The scope form field is a single string containing multiple scopes separated by spaces. Each scope is a string without spaces and represents a specific security permission. Examples include 'users:read', 'users:write', 'instagram_basic', and 'https://www.googleapis.com/auth/drive'. In OAuth2, a scope is just a string that declares a specific permission required; the format and structure are implementation-specific.

OAuth2PasswordRequestForm class fields

OAuth2PasswordRequestForm is a class dependency for form body that declares: username (required), password (required), scope (optional) as a string with scopes separated by spaces, grant_type (optional), client_id (optional), and client_secret (optional). The instance has a scopes attribute (list of strings) instead of scope (the original string).

OAuth2PasswordRequestFormStrict requires grant_type

The OAuth2 spec requires a field grant_type with a fixed value of 'password', but OAuth2PasswordRequestForm does not enforce it. Use OAuth2PasswordRequestFormStrict instead if you need to enforce the grant_type requirement.

OAuth2PasswordRequestForm is a regular class dependency

OAuth2PasswordRequestForm is not a special FastAPI security class like OAuth2PasswordBearer. It is a regular class dependency that could have been written manually or declared as Form parameters directly. FastAPI provides it as a convenience for this common use case.

Using OAuth2PasswordRequestForm as dependency

Import OAuth2PasswordRequestForm and use it as a dependency with Depends in the path operation for /token.

OAuth2 token endpoint response format

The token endpoint response must be a JSON object with token_type (for Bearer tokens, the value should be 'bearer') and access_token (a string containing the access token). These JSON keys must be used exactly as specified to be compliant with OAuth2 specifications.

HTTPException for authentication errors

Use the HTTPException exception to return error responses during authentication, such as 'Incorrect username or password' errors.

Password hashing basics

Hashing converts content (like a password) into a sequence of bytes that looks like gibberish. The same input always produces the same hash output, but the process is not reversible—you cannot convert the hash back to the original password. Never save plaintext passwords in a database; always use password hashing. If a database is stolen, attackers will only have hashes, not plaintext passwords.

WWW-Authenticate header in 401 responses

HTTP 401 'UNAUTHORIZED' status code responses should include a WWW-Authenticate header. For bearer token authentication, the value should be 'Bearer'. This is part of the HTTP specification and helps tools that expect and use this header.

HTTPBasic import and security schema creation

To implement HTTP Basic Auth in FastAPI, import HTTPBasic and HTTPBasicCredentials. Create a security schema by instantiating HTTPBasic(). Use this security schema with a dependency in your path operation, which returns an HTTPBasicCredentials object containing the sent username and password.

HTTP Basic Auth header expectation and 401 response

HTTP Basic Auth expects the application to receive a header containing a username and password. If this header is not received, the application returns HTTP status 401 'Unauthorized'. It also returns a WWW-Authenticate header with the value 'Basic' and an optional realm parameter, which instructs the browser to display the built-in prompt for username and password.

Credential validation using secrets.compare_digest()

Use the Python standard library module secrets with secrets.compare_digest() to securely verify username and password. secrets.compare_digest() accepts bytes or str containing only ASCII characters. To handle non-ASCII characters like 'á' in 'Sebastián', first convert the username and password to UTF-8-encoded bytes before comparison. This protects against timing attacks.

Timing attacks in authentication

A timing attack occurs when an attacker guesses credentials and measures the response time. Standard string comparison returns False immediately when the first character doesn't match, but continues comparing more characters if initial characters match. This means slightly different response times reveal to an attacker which characters were correct, allowing them to narrow down the correct username and password through many attempts in minutes or hours.

secrets.compare_digest() protects against timing attacks

secrets.compare_digest() performs string comparison in constant time, taking the same duration whether comparing 'johndoe' with 'stanleyjobson' or 'stanleyjobsox' with 'stanleyjobson'. This prevents attackers from using response time measurements to determine which characters are correct.

Returning 401 error with WWW-Authenticate header

When credentials are invalid, return an HTTPException with status code 401 and include the WWW-Authenticate header to instruct the browser to display the login prompt again.

Give your agent this brain