Table of Contents
FastAPI is a modern, fast (high-performance) web framework for building APIs with Python 3.7+ based on standard Python type hints. Implementing secure authentication mechanisms like OAuth2 and JWT (JSON Web Tokens) is essential for protecting APIs and managing user access efficiently. This article provides a step-by-step guide on how to implement OAuth2 and JWT authentication in a FastAPI application.
Understanding OAuth2 and JWT
OAuth2 is an authorization framework that enables applications to obtain limited access to user accounts on an HTTP service. It works by delegating user authentication to the service that hosts the user account, and authorizing third-party applications to access the user account.
JWT (JSON Web Token) is a compact, URL-safe token that encodes JSON objects. It is often used in conjunction with OAuth2 to securely transmit user authentication data between parties. JWTs are signed to ensure data integrity and can be encrypted for confidentiality.
Setting Up FastAPI for OAuth2 and JWT
First, install the necessary packages:
pip install fastapi uvicorn python-jose[cryptography]
Creating the FastAPI Application
Begin by importing the required modules and setting up the FastAPI instance:
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from datetime import datetime, timedelta
app = FastAPI()
Defining Security Schemes and Constants
Set up the OAuth2 scheme and secret keys:
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
Creating Utility Functions for JWT
Generate access tokens and verify them:
def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
async def verify_token(token: str, credentials_exception):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
return payload
except JWTError:
raise credentials_exception
Creating Token Endpoint
Define the route to generate tokens after user authentication:
@app.post("/token")
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
user_dict = {"username": form_data.username, "password": form_data.password}
# Here, add actual user validation logic
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(data={"sub": form_data.username}, expires_delta=access_token_expires)
return {"access_token": access_token, "token_type": "bearer"}
Secure Endpoints with OAuth2
Use the OAuth2 scheme to protect routes:
@app.get("/users/me")
async def read_users_me(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(status_code=401, detail="Could not validate credentials")
payload = await verify_token(token, credentials_exception)
username = payload.get("sub")
return {"username": username}
Conclusion
Implementing OAuth2 and JWT authentication in FastAPI enhances the security of your APIs by ensuring that only authorized users can access sensitive endpoints. By following this guide, you can set up a robust authentication system tailored to your application's needs.