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.