Bird
Raised Fist0
FastAPIframework~10 mins

Password hashing with bcrypt in FastAPI - Step-by-Step Execution

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Concept Flow - Password hashing with bcrypt
User inputs password
bcrypt hashes password
Store hashed password
User login attempt
bcrypt verifies password
Access granted or denied
This flow shows how bcrypt hashes a password when a user signs up, stores it, and later verifies it during login.
Execution Sample
FastAPI
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

hashed = pwd_context.hash("mysecret")
valid = pwd_context.verify("mysecret", hashed)
This code hashes a password and then verifies it matches the original password.
Execution Table
StepActionInput PasswordHashed PasswordVerification PasswordVerification Result
1Hash passwordmysecret$2b$12$eW5...hashedvalue
2Verify password$2b$12$eW5...hashedvaluemysecretTrue
3Verify password$2b$12$eW5...hashedvaluewrongpassFalse
4EndVerification complete
💡 Verification stops after checking password matches or not.
Variable Tracker
VariableStartAfter HashAfter Verify TrueAfter Verify FalseFinal
hashedNone$2b$12$eW5...hashedvalue$2b$12$eW5...hashedvalue$2b$12$eW5...hashedvalue$2b$12$eW5...hashedvalue
validNoneNoneTrueFalseFalse
Key Moments - 2 Insights
Why can't we compare the hashed password directly to the plain password?
Because the hashed password is a scrambled version with salt, it looks different each time. We use bcrypt's verify method to check if the plain password matches the hash, as shown in steps 2 and 3 in the execution_table.
Why does hashing the same password twice produce different hashes?
bcrypt adds a random salt each time it hashes, so even the same password results in different hashes. This is why in step 1, the hashed password looks unique.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the verification result when the input password is 'mysecret'?
ATrue
BFalse
CError
DNone
💡 Hint
Check row 2 under 'Verification Result' in the execution_table.
At which step does the hashed password get created?
AStep 3
BStep 2
CStep 1
DStep 4
💡 Hint
Look at the 'Action' column in the execution_table for when hashing happens.
If the password input during verification is wrong, what is the result?
ATrue
BFalse
CException thrown
DPassword rehashed
💡 Hint
See step 3 in the execution_table under 'Verification Result'.
Concept Snapshot
Password hashing with bcrypt in FastAPI:
- Use passlib CryptContext with bcrypt scheme
- Hash passwords with pwd_context.hash(password)
- Verify with pwd_context.verify(plain, hashed)
- Hashes include salt, so same password hashes differ
- Never store plain passwords, only hashed
- Verification returns True if passwords match
Full Transcript
This visual execution shows how bcrypt hashes a password and verifies it. First, the user inputs a password. bcrypt hashes it with a salt, producing a unique hash stored safely. Later, when the user logs in, bcrypt verifies the input password against the stored hash. The verification returns True if they match, False otherwise. Hashing the same password twice produces different hashes because of the salt. We never compare plain passwords directly to hashes; always use bcrypt's verify method. This ensures secure password handling in FastAPI applications.

Practice

(1/5)
1. What is the main purpose of using bcrypt for password hashing in FastAPI?
easy
A. To speed up the login process by caching passwords
B. To encrypt passwords so they can be decrypted later
C. To securely store passwords by converting them into a hashed format
D. To generate random passwords for users automatically

Solution

  1. Step 1: Understand password hashing purpose

    Password hashing converts passwords into a secure format that cannot be reversed, protecting user data.
  2. Step 2: Identify bcrypt role in FastAPI

    bcrypt is used to hash passwords securely, not to encrypt or cache them.
  3. Final Answer:

    To securely store passwords by converting them into a hashed format -> Option C
  4. Quick 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
A. from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
B. import bcrypt pwd_context = bcrypt.PasswordContext()
C. from fastapi.security import bcrypt pwd_context = bcrypt.Context()
D. import passlib pwd_context = passlib.bcrypt()

Solution

  1. Step 1: Recall correct import for bcrypt context

    Passlib's CryptContext is imported from passlib.context and configured with schemes=["bcrypt"].
  2. 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".
  3. Final Answer:

    from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") -> Option A
  4. Quick 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
A. Raises a TypeError
B. True
C. False
D. Prints the hashed password string

Solution

  1. 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.
  2. Step 2: Analyze the verify call

    Since 'secret123' was hashed and then verified against the same string, verify returns True.
  3. Final Answer:

    True -> Option B
  4. Quick 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
A. Using verify method incorrectly with arguments reversed
B. No error; code works correctly
C. Not importing bcrypt module explicitly
D. Missing deprecated="auto" in CryptContext initialization

Solution

  1. Step 1: Check CryptContext initialization

    Best practice is to include deprecated="auto" to handle scheme deprecation warnings.
  2. Step 2: Verify method usage and imports

    verify is used correctly with (plain, hashed). bcrypt import is not needed explicitly with passlib.
  3. Final Answer:

    Missing deprecated="auto" in CryptContext initialization -> Option D
  4. Quick 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
A. 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"}
B. 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}
C. 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"}
D. 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"}

Solution

  1. 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.
  2. 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.
  3. 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.
  4. 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 A
  5. Quick 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