Password hashing with bcrypt helps keep user passwords safe by turning them into secret codes that are hard to guess or steal.
Password hashing with bcrypt in FastAPI
Start learning this pattern below
Jump into concepts and practice - no test required
or
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Syntax
FastAPI
from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") # To hash a password hashed_password = pwd_context.hash("mysecretpassword") # To verify a password is_valid = pwd_context.verify("mysecretpassword", hashed_password)
Use hash() to create a hashed password from plain text.
Use verify() to check if a plain password matches the hashed one.
Examples
FastAPI
hashed = pwd_context.hash("password123")FastAPI
valid = pwd_context.verify("password123", hashed)FastAPI
valid = pwd_context.verify("wrongpass", hashed)Sample Program
This FastAPI app lets users register with a hashed password and login by verifying the password safely.
Passwords are never stored in plain text.
FastAPI
from fastapi import FastAPI, HTTPException from pydantic import BaseModel from passlib.context import CryptContext app = FastAPI() pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") fake_db = {} class User(BaseModel): username: str password: str @app.post("/register") async def register(user: User): if user.username in fake_db: raise HTTPException(status_code=400, detail="User already exists") hashed_password = pwd_context.hash(user.password) fake_db[user.username] = hashed_password return {"msg": "User registered successfully"} @app.post("/login") async def login(user: User): hashed_password = fake_db.get(user.username) if not hashed_password: raise HTTPException(status_code=400, detail="User not found") if not pwd_context.verify(user.password, hashed_password): raise HTTPException(status_code=400, detail="Incorrect password") return {"msg": "Login successful"}
Important Notes
Never store plain passwords; always hash them before saving.
bcrypt automatically adds a random salt to make hashes unique.
Use a strong hashing library like passlib for easy and secure hashing.
Summary
Password hashing protects user data by hiding real passwords.
Use hash() to create hashes and verify() to check passwords.
FastAPI works well with passlib for secure password handling.
Practice
1. What is the main purpose of using
bcrypt for password hashing in FastAPI?easy
Solution
Step 1: Understand password hashing purpose
Password hashing converts passwords into a secure format that cannot be reversed, protecting user data.Step 2: Identify bcrypt role in FastAPI
bcrypt is used to hash passwords securely, not to encrypt or cache them.Final Answer:
To securely store passwords by converting them into a hashed format -> Option CQuick Check:
Password hashing = secure storage [OK]
Hint: Hashing hides passwords, not encrypts or caches them [OK]
Common Mistakes:
- Confusing hashing with encryption
- Thinking bcrypt speeds up login by caching
- Believing bcrypt generates passwords automatically
2. Which of the following is the correct way to import and create a bcrypt password context using passlib in FastAPI?
easy
Solution
Step 1: Recall correct import for bcrypt context
Passlib's CryptContext is imported from passlib.context and configured with schemes=["bcrypt"].Step 2: Check syntax correctness
from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") correctly imports and creates pwd_context with bcrypt scheme and deprecated="auto".Final Answer:
from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") -> Option AQuick Check:
Correct import and setup = from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") [OK]
Hint: Use CryptContext from passlib.context with schemes=['bcrypt'] [OK]
Common Mistakes:
- Importing bcrypt directly instead of CryptContext
- Using wrong module names like fastapi.security
- Calling non-existent constructors
3. Given the following code snippet, what will be the output of
print(pwd_context.verify('secret123', hashed_password)) if hashed_password is generated by hashing 'secret123'?
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
hashed_password = pwd_context.hash('secret123')
print(pwd_context.verify('secret123', hashed_password))medium
Solution
Step 1: Understand pwd_context.hash and verify
pwd_context.hash creates a hashed password from the plain text. verify checks if the plain text matches the hash.Step 2: Analyze the verify call
Since 'secret123' was hashed and then verified against the same string, verify returns True.Final Answer:
True -> Option BQuick Check:
Verify correct password = True [OK]
Hint: Verify returns True if password matches hash [OK]
Common Mistakes:
- Expecting verify to return the hash
- Confusing verify output with hash output
- Thinking verify raises errors on match
4. Identify the error in this FastAPI password hashing code snippet:
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"])
password = "mypassword"
hashed = pwd_context.hash(password)
if pwd_context.verify(password, hashed):
print("Password verified")
else:
print("Verification failed")medium
Solution
Step 1: Check CryptContext initialization
Best practice is to include deprecated="auto" to handle scheme deprecation warnings.Step 2: Verify method usage and imports
verify is used correctly with (plain, hashed). bcrypt import is not needed explicitly with passlib.Final Answer:
Missing deprecated="auto" in CryptContext initialization -> Option DQuick Check:
Include deprecated="auto" to avoid warnings [OK]
Hint: Always add deprecated="auto" in CryptContext [OK]
Common Mistakes:
- Omitting deprecated="auto" causes warnings
- Reversing arguments in verify method
- Importing bcrypt separately when unnecessary
5. You want to create a FastAPI endpoint that accepts a user's plain password, hashes it with bcrypt, and stores it securely. Which of the following code snippets correctly implements this functionality considering best practices?
hard
Solution
Step 1: Check correct use of passlib CryptContext and hashing
from fastapi import FastAPI from passlib.context import CryptContext app = FastAPI() pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @app.post("/register") async def register(password: str): hashed_password = pwd_context.hash(password) # Store hashed_password securely return {"msg": "User registered"} correctly imports CryptContext with deprecated="auto" and hashes the plain string password.Step 2: Validate FastAPI endpoint and parameter types
from fastapi import FastAPI from passlib.context import CryptContext app = FastAPI() pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @app.post("/register") async def register(password: str): hashed_password = pwd_context.hash(password) # Store hashed_password securely return {"msg": "User registered"} uses async def with password as str, which is standard for FastAPI input. It hashes and comments storing securely.Step 3: Compare other options for errors
from fastapi import FastAPI import bcrypt app = FastAPI() @app.post("/register") def register(password: str): hashed_password = bcrypt.hashpw(password, bcrypt.gensalt()) return {"hashed": hashed_password} uses bcrypt module incorrectly with str instead of bytes; from fastapi import FastAPI from passlib.context import CryptContext app = FastAPI() pwd_context = CryptContext(schemes=["bcrypt"]) @app.post("/register") async def register(password: str): hashed_password = pwd_context.hash(password.encode()) return {"msg": "Password hashed"} hashes password.encode() but misses deprecated="auto"; from fastapi import FastAPI from passlib.context import CryptContext app = FastAPI() pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @app.post("/register") async def register(password: bytes): hashed_password = pwd_context.hash(password) return {"msg": "User registered"} expects bytes input which is unusual for FastAPI JSON input.Final Answer:
from fastapi import FastAPI from passlib.context import CryptContext app = FastAPI() pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @app.post("/register") async def register(password: str): hashed_password = pwd_context.hash(password) # Store hashed_password securely return {"msg": "User registered"} -> Option AQuick Check:
Use passlib CryptContext with str input and deprecated="auto" [OK]
Hint: Use passlib CryptContext with str password and deprecated="auto" [OK]
Common Mistakes:
- Using bcrypt module directly with wrong input types
- Omitting deprecated="auto" in CryptContext
- Accepting password as bytes instead of str in FastAPI
