0
0
FastapiHow-ToBeginner · 4 min read

How to Use JWT in FastAPI for Secure Authentication

Use the pyjwt library to create and verify JSON Web Tokens (JWT) in FastAPI. Generate tokens on user login and protect routes by decoding and validating the token in a dependency.
📐

Syntax

This is the basic pattern to use JWT in FastAPI:

  • Create a token: Use jwt.encode() with a payload and secret key.
  • Decode a token: Use jwt.decode() to verify the token and extract data.
  • Protect routes: Use FastAPI dependencies to check the token before allowing access.
python
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
import jwt

SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

def create_access_token(data: dict):
    encoded_jwt = jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

def verify_token(token: str):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        return payload
    except jwt.PyJWTError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid token",
            headers={"WWW-Authenticate": "Bearer"},
        )
💻

Example

This example shows a FastAPI app that creates a JWT token on login and protects a route that requires a valid token.

python
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
import jwt

app = FastAPI()

SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

# Fake user data
fake_user = {"username": "alice", "password": "wonderland"}

def create_access_token(data: dict):
    return jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)

def verify_token(token: str = Depends(oauth2_scheme)):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username = payload.get("sub")
        if username is None:
            raise HTTPException(status_code=401, detail="Invalid token")
        return username
    except jwt.PyJWTError:
        raise HTTPException(status_code=401, detail="Invalid token")

@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    if form_data.username != fake_user["username"] or form_data.password != fake_user["password"]:
        raise HTTPException(status_code=400, detail="Incorrect username or password")
    access_token = create_access_token({"sub": form_data.username})
    return {"access_token": access_token, "token_type": "bearer"}

@app.get("/protected")
async def protected_route(username: str = Depends(verify_token)):
    return {"message": f"Hello, {username}. You are authenticated."}
Output
POST /token with correct username/password returns {"access_token": "<jwt_token>", "token_type": "bearer"} GET /protected with Authorization: Bearer <jwt_token> returns {"message": "Hello, alice. You are authenticated."}
⚠️

Common Pitfalls

  • Using a weak or hardcoded SECRET_KEY can compromise security.
  • Not setting the correct algorithm in jwt.encode and jwt.decode causes verification failures.
  • Failing to handle token expiration or errors properly leads to confusing responses.
  • Not using FastAPI's Depends to enforce token verification on protected routes.
python
from fastapi import HTTPException
import jwt

# Wrong: No algorithm specified in decode
try:
    jwt.decode(token, SECRET_KEY)
except jwt.PyJWTError:
    raise HTTPException(status_code=401, detail="Invalid token")

# Right: Specify algorithm
jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
📊

Quick Reference

StepDescriptionCode Snippet
1Create JWT token with payload and secretjwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
2Decode and verify tokenjwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
3Use FastAPI dependency to get tokentoken: str = Depends(oauth2_scheme)
4Raise HTTPException on invalid tokenraise HTTPException(status_code=401, detail="Invalid token")
5Protect routes by requiring verified token@app.get('/protected')\nasync def route(user=Depends(verify_token)):

Key Takeaways

Always use a strong SECRET_KEY and specify the algorithm when encoding and decoding JWTs.
Create tokens on login and verify them in dependencies to protect FastAPI routes.
Handle exceptions to return clear 401 Unauthorized responses for invalid tokens.
Use FastAPI's OAuth2PasswordBearer to extract tokens from requests easily.
Test your JWT flow by requesting tokens and accessing protected endpoints with them.