🚀 Lesson 5 — Authentication & Authorization in FastAPI (JWT, OAuth2, Password Hashing)
This is one of the most important and most asked things in FastAPI interviews and real-world systems.
By the end of this lesson, you’ll be able to build:
✔ Login System
✔ Register User
✔ Secure Passwords (Hashing)
✔ JWT Tokens
✔ Protected Routes
✔ OAuth2 Password Flow
✔ Role-based access (Admin/User)
Let’s start. 🔥
🎯 What You Will Learn Today
✔ Authentication vs Authorization
✔ Password hashing (never store plain text)
✔ JWT token creation
✔ Secure login + token generation
✔ Protect APIs using OAuth2 scheme
✔ Role-based access example
🧠 1. Authentication vs Authorization (Very Simple)
- Authentication → “Who are you?”
(Login using username/password) - Authorization → “What can you access?”
(Admin? Normal user? Can delete/update?)
FastAPI supports both using JWT & OAuth2.
🔐 2. Install Dependencies
pip install python-jose passlib[bcrypt]
- python-jose → for JWT tokens
- passlib + bcrypt → for password hashing
🧂 3. Password Hashing (NEVER store raw passwords)
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str):
return pwd_context.hash(password)
def verify_password(plain, hashed):
return pwd_context.verify(plain, hashed)
Test:
hashed = hash_password("admin123")
verify_password("admin123", hashed) # True
verify_password("wrongpass", hashed) # False
🏗 4. User Model (Pydantic)
from pydantic import BaseModel
class User(BaseModel):
username: str
password: str
Database simulation:
db = {} # {username: hashed_password}
🔐 5. JWT Token Setup
from datetime import datetime, timedelta
from jose import jwt
SECRET_KEY = "SUPER_SECRET_KEY_12345"
ALGORITHM = "HS256"
def create_token(data: dict):
payload = data.copy()
payload["exp"] = datetime.utcnow() + timedelta(minutes=30)
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
🚪 6. Register Endpoint (Signup)
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.post("/register")
def register(user: User):
if user.username in db:
raise HTTPException(400, "User already exists")
hashed_pw = hash_password(user.password)
db[user.username] = hashed_pw
return {"msg": "User registered"}
🔓 7. Login Endpoint → Issue JWT
class TokenResponse(BaseModel):
access_token: str
token_type: str = "bearer"
@app.post("/login", response_model=TokenResponse)
def login(user: User):
if user.username not in db:
raise HTTPException(400, "Invalid username")
if not verify_password(user.password, db[user.username]):
raise HTTPException(400, "Invalid password")
token = create_token({"sub": user.username})
return TokenResponse(access_token=token)
Login returns:
{
"access_token": "<JWT_TOKEN>",
"token_type": "bearer"
}
🛡 8. Protect Routes Using OAuth2 Scheme
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/login")
🔑 9. Decode Token + Get Current User
def get_current_user(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username = payload.get("sub")
if username is None:
raise HTTPException(401, "Invalid token")
return username
except:
raise HTTPException(401, "Invalid token or expired")
🛠 10. Protected Route Example
from fastapi import Depends
@app.get("/profile")
def profile(user: str = Depends(get_current_user)):
return {"logged_in_as": user}
Try accessing /profile without a token → 401 Unauthorized
Use Swagger:
Click Authorize → paste token → access allowed ✔
⭐ 11. Role-Based Access (Admin Only)
Add roles:
class User(BaseModel):
username: str
password: str
role: str = "user" # user/admin
Store role in DB:
db[user.username] = {"password": hashed_pw, "role": user.role}
Check role:
def is_admin(user: str = Depends(get_current_user)):
if db[user]["role"] != "admin":
raise HTTPException(403, "Admins only!")
return user
Admin-only API:
@app.get("/admin")
def admin_dashboard(user: str = Depends(is_admin)):
return {"msg": f"Welcome Admin {user}"}
🧪 12. Complete Authentication Flow
Step 1: Register a user
→ Store hashed password
Step 2: Login
→ Verify password
→ Create JWT token
Step 3: Protect routes
→ Validate token
→ Allow only authenticated users
Step 4: Role-based access
→ Allow admin-only endpoints
This is exactly what:
- Banking apps
- E-commerce
- Admin dashboards
- AI platforms
- SaaS tools
use in production.
📌 Lesson 5 Summary
You learned how to build:
✔ Complete Login system
✔ Register endpoint
✔ Hashed passwords
✔ JWT tokens
✔ Protected API routes
✔ OAuth2 Password flow
✔ Role-based access
This is interview gold and industry standard.
🚀 Ready for Lesson 6 — Databases (SQL + NoSQL, SQLAlchemy, CRUD, relationships, async DB)?
Should I continue with Lesson 6 now?