Mastering Security in FastAPI: A Comprehensive Guide to OAuth2 with Password Hashing and JWT Bearer Tokens
Security is paramount in modern web applications, and FastAPI provides robust solutions for handling authentication and authorization. In this comprehensive guide, we will dive deep into OAuth2 with Password Hashing and JWT Bearer Tokens to secure your FastAPI applications. We will cover the core concepts, practical implementations, and provide valuable tips and insights along the way.
Introduction to OAuth2
OAuth2 is an open standard for access delegation commonly used for token-based authentication and authorization on the internet. It allows third-party services to exchange credentials for access tokens, which can then be used to access the user's data without exposing their credentials. In this section, we will go over the basics of OAuth2 and how it integrates with FastAPI.
Understanding OAuth2 Flow
OAuth2 defines several flows for different use cases, but the most common one is the Resource Owner Password Credentials flow. Here's a general outline of the flow:
- The client requests a token from the authorization server by providing the username and password of the resource owner.
- The authorization server validates the credentials and issues an access token.
- The client uses the access token to authenticate and access protected resources from the resource server.
Implementing Password Hashing
Storing raw passwords is a significant security risk. To mitigate this, we hash passwords before storing them in our database. FastAPI doesn't come with built-in support for password hashing, but we can use the passlib
library to achieve this securely.
Setting Up Password Hashing
First, install passlib
:
pip install passlib[bcrypt]
Then, create a utility function to hash passwords:
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
Using Hashed Passwords in FastAPI
When a user registers or updates their password, hash it before saving:
# Hash and save password when creating a new user
new_user.password = hash_password(new_user.password)
# Verifying password during login
if not verify_password(login_data.password, stored_user.password):
raise HTTPException(status_code=400, detail="Incorrect username or password")
JWT Bearer Tokens
JSON Web Tokens (JWT) are a compact, URL-safe means of representing claims to be transferred between two parties. We use JWTs as bearer tokens to authenticate API requests. FastAPI's fastapi.security
module provides easy integration with JWT Bearer tokens.
Generating JWT Tokens
To generate JWT tokens, install pyjwt
:
pip install pyjwt
Create a function to generate tokens:
import jwt
from datetime import datetime, timedelta
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
def create_access_token(data: dict) -> str:
to_encode = data.copy()
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
Verifying JWT Tokens
To verify and decode JWT tokens:
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def verify_token(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return payload
except JWTError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
Securing Endpoints
Finally, use the verify_token
dependency to secure your endpoints:
@app.get("/protected-route")
async def protected_route(current_user: dict = Depends(verify_token)):
return {"message": "This is a protected route", "user": current_user}
Conclusion
In this guide, we've covered the essentials of securing FastAPI applications with OAuth2, password hashing, and JWT bearer tokens. By understanding these concepts and implementing the provided examples, you will enhance the security of your applications significantly. Ensure to keep your secret keys safe and follow best practices. Happy coding!