JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. A JWT consists of three parts: a header, a payload, and a signature. The header typically contains information about the token type and the signing algorithm. The payload contains the claims, which can be either registered, public, or private claims. The signature is used to verify that the sender of the JWT is who it claims to be and to ensure that the message wasn’t changed along the way.
First, make sure you have Python installed on your system. Then, create a virtual environment and install FastAPI and other necessary libraries:
# Create a virtual environment
python -m venv venv
# Activate the virtual environment
# On Windows
venv\Scripts\activate
# On Linux/Mac
source venv/bin/activate
# Install FastAPI and Uvicorn
pip install fastapi uvicorn python-jose[cryptography] passlib[bcrypt]
Here is a simple FastAPI application structure:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
To run the application, use the following command:
uvicorn main:app --reload
You need a secret key to sign and verify JWT tokens. You can generate a random secret key using the following Python code:
import secrets
SECRET_KEY = secrets.token_urlsafe(32)
print(SECRET_KEY)
Here is an example of generating a JWT token in FastAPI:
from fastapi import Depends, FastAPI
from jose import JWTError, jwt
from datetime import datetime, timedelta
from typing import Optional
# Secret key and algorithm
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
app = FastAPI()
@app.post("/token")
def login():
data = {"sub": "user123"}
access_token = create_access_token(data)
return {"access_token": access_token, "token_type": "bearer"}
def verify_token(token: str):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
return username
except JWTError:
raise credentials_exception
from fastapi import Depends, FastAPI, HTTPException
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from datetime import datetime, timedelta
from typing import Optional
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
app = FastAPI()
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
def verify_token(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=401,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
return username
except JWTError:
raise credentials_exception
@app.post("/token")
def login():
data = {"sub": "user123"}
access_token = create_access_token(data)
return {"access_token": access_token, "token_type": "bearer"}
@app.get("/protected")
def protected_route(username: str = Depends(verify_token)):
return {"message": f"Hello, {username}! This is a protected route."}
Implementing JWT authentication in FastAPI provides a secure and efficient way to handle user authentication and authorization. By understanding the fundamental concepts, following common practices, and implementing best practices, you can build robust and secure web applications. JWTs are well-suited for modern web architectures, such as microservices, due to their stateless and portable nature.