How to Use Passlib with FastAPI for Secure Password Hashing
Use
passlib.context.CryptContext in FastAPI to hash passwords securely and verify them during login. Create a CryptContext instance with a hashing scheme like bcrypt, then use its hash() and verify() methods to handle passwords safely.Syntax
To use Passlib with FastAPI, first create a CryptContext object specifying the hashing algorithms. Then use hash() to create a hashed password and verify() to check a plain password against the hash.
- CryptContext(schemes=[...]): Defines which hash algorithms to use.
- hash(password): Hashes the plain password.
- verify(plain_password, hashed_password): Checks if the plain password matches the hash.
python
from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") # Hash a password hashed_password = pwd_context.hash("mysecretpassword") # Verify a password is_valid = pwd_context.verify("mysecretpassword", hashed_password)
Example
This example shows a simple FastAPI app that hashes a password on signup and verifies it on login using Passlib's CryptContext. It demonstrates secure password handling without storing plain text passwords.
python
from fastapi import FastAPI, HTTPException from pydantic import BaseModel from passlib.context import CryptContext app = FastAPI() pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") fake_user_db = {} class User(BaseModel): username: str password: str @app.post("/signup") async def signup(user: User): if user.username in fake_user_db: raise HTTPException(status_code=400, detail="User already exists") hashed_password = pwd_context.hash(user.password) fake_user_db[user.username] = hashed_password return {"msg": "User created successfully"} @app.post("/login") async def login(user: User): hashed_password = fake_user_db.get(user.username) if not hashed_password or not pwd_context.verify(user.password, hashed_password): raise HTTPException(status_code=401, detail="Invalid username or password") return {"msg": "Login successful"}
Common Pitfalls
- Not using a
CryptContextand hashing passwords manually can lead to insecure implementations. - Storing plain text passwords instead of hashed versions is a serious security risk.
- Using outdated or weak hashing algorithms instead of modern ones like
bcryptorargon2. - Forgetting to verify passwords properly during login causes authentication failures.
Always use CryptContext with a recommended scheme and verify passwords with its verify() method.
python
from passlib.context import CryptContext # Wrong: Storing plain password plain_password = "mypassword" stored_password = plain_password # insecure! # Right: Hashing password pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") stored_password = pwd_context.hash(plain_password) # Wrong: Verifying by direct string compare is_valid = (plain_password == stored_password) # always False # Right: Use verify method is_valid = pwd_context.verify(plain_password, stored_password)
Quick Reference
- CryptContext(schemes=["bcrypt"]): Create password hashing context.
- hash(password): Hash a plain password.
- verify(plain, hashed): Check if plain password matches hash.
- Use
bcryptorargon2for strong security. - Never store or compare plain passwords directly.
Key Takeaways
Always hash passwords using Passlib's CryptContext before storing them.
Use the verify() method to check passwords securely during login.
Choose strong hashing schemes like bcrypt or argon2 in CryptContext.
Never store or compare plain text passwords directly.
Integrate Passlib with FastAPI to keep user authentication safe and simple.