FastAPI: From Basics to Production · Authentication and Security

JWT Access Tokens and the Current User

Issue and verify short-lived JWTs and resolve the current user.

Issue short-lived JWT access tokens (5–15 minutes) signed with a strong secret (HS256) or private key (RS256/EdDSA), containing sub, exp, iat and optionally aud/iss. Verify the signature and claims on every request with an explicit algorithm list, then load the user. Use refresh tokens (rotated, revocable, stored server-side) for long sessions, preferably in HttpOnly cookies for browser apps.

from datetime import UTC, datetime, timedelta
import jwt
from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/token")


def create_access_token(user: User) -> str:
    now = datetime.now(UTC)
    payload = {"sub": str(user.id), "iat": now, "exp": now + timedelta(minutes=15), "aud": "bookstore-api"}
    return jwt.encode(payload, settings.jwt_secret.get_secret_value(), algorithm="HS256")


async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)], db: DB) -> User:
    try:
        payload = jwt.decode(token, settings.jwt_secret.get_secret_value(), algorithms=["HS256"], audience="bookstore-api")
    except jwt.InvalidTokenError:
        raise HTTPException(401, "Invalid or expired token", headers={"WWW-Authenticate": "Bearer"})
    user = await db.get(User, int(payload["sub"]))
    if user is None or not user.active:
        raise HTTPException(401, "Inactive user")
    return user

Common pitfalls

  • Accepting the algorithm from the token header or allowing none.
  • Long-lived access tokens that can't be revoked.
  • Putting sensitive data in the JWT payload (it's only base64-encoded).

Key points

  • Short-lived, signed tokens
  • Pin algorithms; verify exp/aud
  • Refresh tokens for long sessions

Further reading: PyJWT usage

Practice questions

Why pass algorithms=['HS256'] explicitly to jwt.decode?

Answer

To prevent algorithm confusion attacks where a token chooses a weaker or different algorithm (like none or using a public key as an HMAC secret).

Is data inside a JWT secret?

Answer

No. Signed JWTs are base64url-encoded and readable by anyone; the signature only prevents tampering. Don't put sensitive data in them.

Open in the app to mark lessons complete, take notes and track your progress.