Script Valley
FastAPI: Build Production Python APIs
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.

Up next

How to create and verify JWT tokens in FastAPI

Sign in to track progress