python 126 lines · 4 tabs

Reusable OAuth2 Password Bearer JWT Authentication Dependency in FastAPI

Shared by codesnips Sep 2026
4 tabs
from datetime import datetime, timedelta, timezone

from fastapi.security import OAuth2PasswordBearer
from jose import jwt
from passlib.context import CryptContext

SECRET_KEY = "change-me-in-production-use-env-var"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")


def verify_password(plain_password: str, hashed_password: str) -> bool:
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password: str) -> str:
    return pwd_context.hash(password)


def create_access_token(subject: str, expires_delta: timedelta | None = None) -> str:
    expire = datetime.now(timezone.utc) + (
        expires_delta or timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    )
    payload = {"sub": subject, "exp": expire}
    return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
4 files · python Explain with highlit

This snippet shows the standard way to protect FastAPI routes with a bearer token issued from a password login flow, then decoded and validated on every request through a reusable dependency. The design centers on FastAPI's dependency injection: a single get_current_user dependency does the token work once and is reused everywhere via Depends, so route handlers stay free of auth boilerplate.

In security.py, OAuth2PasswordBearer is instantiated with a tokenUrl pointing at the login endpoint. That instance is itself a callable dependency — when used as Depends(oauth2_scheme), it extracts the Authorization: Bearer <token> header, raises a 401 automatically when it is missing, and also drives the interactive Swagger UI "Authorize" button. The module wraps python-jose and passlib so the rest of the app never touches raw crypto: create_access_token signs a payload with an exp claim and HS256, while verify_password and get_password_hash use a bcrypt CryptContext. Keeping the secret and algorithm here centralizes the trust boundary.

The core of the pattern lives in deps.py. get_current_user depends on both oauth2_scheme (for the raw token) and a DB session, decodes the JWT inside a try/except JWTError, and pulls the subject from the sub claim. A shared credentials_exception returns 401 with the WWW-Authenticate: Bearer header required by the OAuth2 spec. Because decoding failures, missing claims, and unknown users all funnel to the same exception, the endpoint never leaks which check failed. A second dependency, get_current_active_user, layers on top to reject disabled accounts, demonstrating how dependencies compose to build coarser guarantees from smaller ones.

In auth_router.py, the /token route accepts OAuth2PasswordRequestForm, which parses the form-encoded username/password that OAuth2 clients send, authenticates against the store, and returns a Token response. The protected /users/me route simply declares current_user: User = Depends(get_current_active_user) and receives a fully validated user.

The main trade-off of stateless JWTs is revocation: tokens remain valid until exp, so short lifetimes or a denylist are needed for immediate logout. Reaching for this pattern makes sense whenever an API needs standards-compliant token auth with minimal per-route code.


Related snips

Share this code

Here's the card — post it anywhere.

Reusable OAuth2 Password Bearer JWT Authentication Dependency in FastAPI — share card
Link copied