FastAPI Security & OAuth — Core Concepts
What OAuth2 does in FastAPI
OAuth2 is an authorization framework — it defines how applications get permission to act on behalf of users. In FastAPI, it’s most commonly used with JWT (JSON Web Tokens) to create a stateless authentication system: the user logs in, gets a token, and includes that token in every subsequent request.
FastAPI provides security utilities that integrate directly with its dependency injection system and auto-generated OpenAPI documentation. When you add a security dependency to a route, FastAPI both enforces the check and documents it in the Swagger UI.
The OAuth2 password flow
The simplest OAuth2 flow for first-party applications (where you control both the frontend and backend):
- User sends credentials to a
/tokenendpoint (username and password in a form body) - Server validates credentials against the database
- Server creates a JWT containing the user’s identity and permissions
- Server returns the token to the client
- Client includes the token in the
Authorization: Bearer <token>header on subsequent requests - Server validates the token on each request using a dependency
FastAPI’s OAuth2PasswordBearer class handles steps 5-6. It extracts the token from the Authorization header and passes it to your validation function.
JWT tokens explained
A JWT is a signed string containing three parts: header (algorithm info), payload (user data), and signature (proof it wasn’t tampered with).
The payload typically includes:
sub(subject): the user’s ID or usernameexp(expiration): when the token stops being validscopes: what the token is authorized to do
The server signs the JWT with a secret key. When a request arrives with a token, the server verifies the signature using the same key. If the signature is valid and the token hasn’t expired, the request is authenticated.
No database lookup is needed to validate the token — that’s why it’s “stateless.” The tradeoff: you can’t revoke a JWT before it expires without adding a revocation check (which reintroduces state).
Scopes for permission control
OAuth2 scopes let you define fine-grained permissions. A token might have scopes like read:items, write:items, admin:users. Each route can require specific scopes:
Routes that require admin:users reject tokens that only have read:items. This gives you role-based access control without separate role-checking logic in every route.
FastAPI’s Security dependency (an extension of Depends) lets you specify required scopes. The auto-generated documentation shows which scopes each endpoint requires.
Token refresh pattern
Access tokens should be short-lived (15-60 minutes) to limit damage if stolen. But forcing users to log in every hour is annoying. The solution: refresh tokens.
The login endpoint returns two tokens:
- Access token: Short-lived, used for API requests
- Refresh token: Long-lived, used only to get new access tokens
When the access token expires, the client sends the refresh token to a /token/refresh endpoint. The server validates the refresh token and issues a new access token. If the refresh token is also expired, the user must log in again.
Refresh tokens should be stored securely (HTTP-only cookies, not localStorage) and can be revoked server-side since they’re checked against a database.
Third-party OAuth2 (Login with Google/GitHub)
When you want users to log in using Google, GitHub, or another provider:
- Your app redirects the user to the provider’s authorization page
- The user logs in there and grants permission
- The provider redirects back to your app with an authorization code
- Your app exchanges the code for an access token from the provider
- Your app uses the token to fetch the user’s profile from the provider
- Your app creates a local user record and issues its own JWT
FastAPI doesn’t have built-in OAuth2 provider integration (it handles the token validation side), so libraries like authlib or python-social-auth handle the provider communication.
Common misconception
Many developers think OAuth2 is only for “Login with Google” scenarios. In practice, OAuth2 is used far more often for first-party authentication — your own login form, your own tokens, your own user database. The “Login with Google” flow (Authorization Code Grant) is just one of several OAuth2 flows. The Password Grant and Client Credentials Grant are equally important and more common in API-first applications.
Security pitfalls
- Storing tokens in localStorage: Vulnerable to XSS attacks. Use HTTP-only cookies for browser-based apps.
- No token expiration: Tokens that never expire are permanent credentials. If leaked, they provide indefinite access.
- Weak signing keys: Using short or predictable secret keys makes tokens forgeable. Use 256-bit random keys minimum.
- Missing HTTPS: Tokens sent over HTTP can be intercepted by anyone on the network. Always use HTTPS in production.
The one thing to remember: FastAPI’s OAuth2 integration gives you stateless JWT authentication with scopes for permissions, automatic Swagger documentation, and dependency injection for clean route-level security — but short token lifetimes, secure storage, and HTTPS are non-negotiable for production.
See Also
- Python Aiohttp Client Understand Aiohttp Client through a practical analogy so your Python decisions become faster and clearer.
- Python Api Client Design Why building your own API client in Python is like creating a TV remote that only has the buttons you actually need.
- Python Api Documentation Swagger Swagger turns your Python API into an interactive playground where anyone can click buttons to try it out — no coding required.
- Python Api Mocking Responses Why testing with fake API responses is like rehearsing a play with stand-ins before the real actors show up.
- Python Api Pagination Clients Why APIs send data in pages, and how Python handles it — like reading a book one chapter at a time instead of swallowing the whole thing.