Authentication and SecurityLesson 4.1
How to hash passwords and verify them in FastAPI with passlib
passlib CryptContext, bcrypt algorithm, hash function, verify function, never store plaintext, timing-safe comparison, password hashing best practices
Password Hashing with passlib
Never store plaintext passwords. FastAPI projects use passlib with the bcrypt algorithm. Bcrypt is slow by design — that cost makes brute-force attacks expensive.
Install
pip install passlib[bcrypt]Create a CryptContext
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: str, hashed: str) -> bool:
return pwd_context.verify(plain, hashed)
Store only hash_password(password) in the database. Never log or return the plaintext password anywhere in your application.
Using it in a registration route
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
class UserCreate(BaseModel):
email: str
password: str
@app.post("/register")
def register(user: UserCreate):
hashed = hash_password(user.password)
# save user.email + hashed to DB
return {"email": user.email}
pwd_context.verify uses a timing-safe comparison internally. Never compare hashes with == directly — that is vulnerable to timing attacks. Always use the library's verify function.
