नमस्ते दोस्तों!
स्वागत है The Easy Master पर!
क्या आप FastAPI में API बना रहे हैं? और अब सोच रहे हैं – “इस API को secure कैसे करूँ? Kaise sirf registered users hi access kar payein?”
Yeh bohot common problem hai.
Maine bhi jab pehli baar API banayi thi, toh sab endpoints public the. Koi bhi user delete kar sakta tha, koi bhi data change kar sakta tha. Ek din ek friend ne mazak mein saara data delete kar diya. Us din samajh aaya – authentication kitna important hai!
Tab maine JWT authentication implement kiya – aur ab API fully secure hai.
Is FastAPI authentication JWT Hindi article mein main aapko sikhata hoon:
✅ JWT kya hota hai – simple example ke saath
✅ Password hashing – kabhi bhi plain password mat rakhna
✅ User registration – signup endpoint
✅ User login – JWT token generate karna
✅ Protected routes – Depends() ke saath token verify
✅ Token refresh – access token + refresh token pattern
✅ Real project – complete auth system with database
End mein cheat sheet, practice prompts, aur feature image prompt bhi milega.
Chaliye secure API banana shuru karte hain! 🚀
Table of Contents
1. JWT Authentication Kya Hai? – Simple Samjho
JWT = JSON Web Token.
Ek secure string (token) jo user ke identity ko represent karta hai. Jab user login karta hai, server ek token generate karta hai aur user ko deta hai. User har request mein yeh token bhejta hai (usually Authorization header mein). Server token verify karta hai – agar valid hai toh request allow, nahi toh reject.
Token ka structure (eye candy nahi, but important):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJleHAiOjE3MDAwMDAwfQ.h6EbCuQ6B_7QToken ke 3 parts hote hain (dot se alag):
- Header – algorithm info
- Payload – data (user id, expiry time, etc.)
- Signature – verification ke liye
Kaam kaise karta hai (step by step):
- User → POST
/loginwith email & password - Server → password check, agar sahi to generate JWT token
- Server → token send karta hai user ko (response mein)
- User → har protected endpoint mein token bhejta hai:
Authorization: Bearer <token> - Server → token verify karta hai, agar valid to data return, nahi to 401 Unauthorized
Token expiry (access token short-lived, refresh token long-lived):
- Access token – 15 min to 1 hour (short)
- Refresh token – 7 days to 30 days (long) – naya access token generate karne ke liye
2. Project Setup – Dependencies Install Karein
# Virtual environment banao
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Packages install karo
pip install fastapi "uvicorn[standard]" python-jose[cryptography] passlib[bcrypt] python-multipart bcryptHar package kya karta hai:
| Package | Role |
|---|---|
fastapi + uvicorn | Web framework and server |
python-jose[cryptography] | JWT token create aur verify |
passlib[bcrypt] | Password hashing |
bcrypt | Hashing algorithm |
python-multipart | Form data support |
Database ke liye aap SQLModel / SQLAlchemy bhi add kar sakte ho, lekin simplicity ke liye hum pehle in-memory storage use karenge.
3. Password Hashing – Argon2 / Bcrypt
Kabhi bhi plain password store mat karo! – Agar database leak hui toh sabki password public ho jayegi.
Hashing ka matlab – password ko ek irreversible string mein convert karna.
from passlib.context import CryptContext
# Password hashing context
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
"""Plain password ko hash mein convert karein"""
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""Check karein ki plain password hash se match karta hai ya nahi"""
return pwd_context.verify(plain_password, hashed_password)
# Example
hashed = hash_password("mysecret123")
print(hashed) # $2b$12$KxJqXcQ... (looks random)
# Verify
print(verify_password("mysecret123", hashed)) # True
print(verify_password("wrongpass", hashed)) # False💡 Personal Experience: Maine pehle plain password store kiye the (learning phase mein). Ek din friend ne database dekhi toh sabki password pata chal gayi. Uske baad se hamesha hash karta hoon. Koi excuse nahi – hashing karna bohot easy hai.
4. User Registration – Signup Endpoint
Pehla step – user ko database mein register karna.
auth.py – (complete code):
from fastapi import FastAPI, HTTPException, status, Depends
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel, EmailStr, Field
from typing import Optional, Dict
from datetime import datetime, timedelta
from jose import JWTError, jwt
from passlib.context import CryptContext
import os
app = FastAPI(title="JWT Auth API")
# ---------- Configuration ----------
SECRET_KEY = "your-super-secret-key-change-in-production" # Use env variable!
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# Password hashing
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# OAuth2 scheme – for extracting token from Authorization header
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
# ---------- Models ----------
class UserBase(BaseModel):
email: EmailStr
username: str = Field(min_length=3, max_length=20)
class UserCreate(UserBase):
password: str = Field(min_length=6)
class UserInDB(UserBase):
id: int
hashed_password: str
created_at: datetime
class Token(BaseModel):
access_token: str
token_type: str
class TokenData(BaseModel):
email: Optional[str] = None
# ---------- Fake Database (In-memory) ----------
fake_users_db: Dict[int, UserInDB] = {}
user_id_counter = 1
# ---------- Helper Functions ----------
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)
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
def get_user_by_email(email: str):
for user in fake_users_db.values():
if user.email == email:
return user
return None
# ---------- Register Endpoint ----------
@app.post("/register", response_model=UserBase, status_code=status.HTTP_201_CREATED)
async def register(user_data: UserCreate):
global user_id_counter
# Check if user already exists
existing_user = get_user_by_email(user_data.email)
if existing_user:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Email already registered"
)
# Create new user
hashed_password = hash_password(user_data.password)
new_user = UserInDB(
id=user_id_counter,
email=user_data.email,
username=user_data.username,
hashed_password=hashed_password,
created_at=datetime.utcnow()
)
fake_users_db[user_id_counter] = new_user
user_id_counter += 1
return new_userTesting with Postman / curl:
curl -X POST "http://localhost:8000/register" \
-H "Content-Type: application/json" \
-d '{"email":"rahul@example.com","username":"rahul123","password":"secret123"}'Response:
{"email":"rahul@example.com","username":"rahul123"}5. User Login – JWT Token Generate Karein
Ab login endpoint – user email/password dega, server token return karega.
from fastapi.security import OAuth2PasswordRequestForm
@app.post("/login", response_model=Token)
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
"""
OAuth2PasswordRequestForm gives `username` and `password` fields.
Note: `username` field mein email dalna hota hai (by default username hai, but we use email)
"""
user = get_user_by_email(form_data.username)
if not user or not verify_password(form_data.password, user.hashed_password):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect email or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.email}, expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}Testing login:
curl -X POST "http://localhost:8000/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=rahul@example.com&password=secret123"Response:
{"access_token":"eyJhbGc...","token_type":"bearer"}🔐 Important: Token ko client-side (React, mobile app) mein store karna. Never store in localStorage if possible (httpOnly cookie is safer). But for learning, localStorage is fine.
6. Protected Routes – Token Verify Kaise Karein
Ab hum ek protected endpoint banayenge – sirf valid token wale users access kar sakte hain.
# ---------- Token Verification ----------
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
email: str = payload.get("sub")
if email is None:
raise credentials_exception
token_data = TokenData(email=email)
except JWTError:
raise credentials_exception
user = get_user_by_email(token_data.email)
if user is None:
raise credentials_exception
return user
# ---------- Protected Endpoint ----------
@app.get("/users/me")
async def read_users_me(current_user: UserInDB = Depends(get_current_user)):
"""Only accessible with valid token. Returns current user info."""
return {
"id": current_user.id,
"email": current_user.email,
"username": current_user.username,
"created_at": current_user.created_at
}Testing protected endpoint:
# First login to get token
TOKEN=$(curl -s -X POST "http://localhost:8000/login" \
-d "username=rahul@example.com&password=secret123" | jq -r '.access_token')
# Then access protected route
curl -X GET "http://localhost:8000/users/me" \
-H "Authorization: Bearer $TOKEN"Agar invalid token ya no token:
{"detail":"Could not validate credentials"}7. Current User Dependency – Har Jagah Use Karo
get_current_user dependency ko aap kisी भी endpoint mein use kar sakte ho. Isse user object automatically available ho jayega.
@app.get("/users/me/orders")
async def get_my_orders(current_user: UserInDB = Depends(get_current_user)):
# current_user ke paas logged-in user ki info hai
return {"user_id": current_user.id, "orders": []}
# Admin only example
@app.get("/admin/users")
async def get_all_users(current_user: UserInDB = Depends(get_current_user)):
# Admin check (example: email domain ya role field)
if not current_user.email.endswith("@admin.com"):
raise HTTPException(status_code=403, detail="Admin access required")
return list(fake_users_db.values())Agar har endpoint mein current_user chahiye, toh global dependency bana sakte ho:
app = FastAPI(dependencies=[Depends(get_current_user)])
# Ab saare endpoints automatically require authenticationPro Tip:
get_current_userke andar database se user fetch karna expensive ho sakta hai – cache karo ya token mein extra info (like user role) bhi include kar sakte ho.
8. Token Refresh – Access Token Expire Ho Jaye Toh
JWT access token short-lived hota hai (security ke liye). Lekin user ko baar-baar login karne se bachane ke liye Refresh Token use karte hain.
Refresh Token Pattern:
- Login: server access_token (15 min) + refresh_token (7 days) return karega.
- Jab access_token expire ho, client refresh_token bhej kar naya access_token le lega.
- Refresh_token bhi expire ho jaye toh user ko login karna padega.
Extended code (add to existing):
# Add more config
REFRESH_TOKEN_EXPIRE_DAYS = 7
def create_refresh_token(data: dict):
expire = datetime.utcnow() + timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS)
to_encode = data.copy()
to_encode.update({"exp": expire, "type": "refresh"})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
# Modify login to return both tokens
@app.post("/login", response_model=Token) # We'll adjust response model later
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
# ... same user verification ...
access_token = create_access_token(data={"sub": user.email})
refresh_token = create_refresh_token(data={"sub": user.email})
return {
"access_token": access_token,
"refresh_token": refresh_token, # new
"token_type": "bearer"
}
# Refresh endpoint
class RefreshTokenRequest(BaseModel):
refresh_token: str
@app.post("/refresh", response_model=Token)
async def refresh_access_token(refresh_data: RefreshTokenRequest):
try:
payload = jwt.decode(refresh_data.refresh_token, SECRET_KEY, algorithms=[ALGORITHM])
if payload.get("type") != "refresh":
raise HTTPException(status_code=401, detail="Invalid token type")
email = payload.get("sub")
if email is None:
raise HTTPException(status_code=401, detail="Invalid refresh token")
user = get_user_by_email(email)
if user is None:
raise HTTPException(status_code=401)
new_access_token = create_access_token(data={"sub": user.email})
return {"access_token": new_access_token, "token_type": "bearer"}
except JWTError:
raise HTTPException(status_code=401, detail="Invalid or expired refresh token")Personal Experience: Refresh token implement karne ke baad users ko bar-bar login nahi karna padta, lekin security bhi maintain rehti hai. Lekin refresh tokens ko database mein store karna chahiye aur revoke karne ka mechanism hona chahiye (logout ke time). Beginners ke liye basic access token bhi sufficient hai.
9. Real Project – Complete Auth System (PostgreSQL + SQLModel)
Ab sab kuch milakar ek production-style auth system banate hain with database.<details> <summary>📁 Full project code – click to expand</summary>
models.py:
from sqlmodel import SQLModel, Field
from datetime import datetime
from typing import Optional
class User(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
email: str = Field(unique=True, index=True)
username: str = Field(unique=True, index=True)
hashed_password: str
is_active: bool = Field(default=True)
is_superuser: bool = Field(default=False)
created_at: datetime = Field(default_factory=datetime.utcnow)auth.py (full):
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from sqlmodel import select
from sqlalchemy.ext.asyncio import AsyncSession
from .database import get_db
from .models import User
from .config import SECRET_KEY, ALGORITHM
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
async def get_current_user(
token: str = Depends(oauth2_scheme),
db: AsyncSession = Depends(get_db)
) -> User:
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
email: str = payload.get("sub")
if email is None:
raise credentials_exception
except JWTError:
raise credentials_exception
result = await db.execute(select(User).where(User.email == email))
user = result.scalar_one_or_none()
if user is None:
raise credentials_exception
return userroutes/users.py: Protected endpoint to get current user.</details>
10. Common Mistakes (aur Unka Solution!)
| Mistake | Why? | Solution |
|---|---|---|
| Secret key hardcoded aur commit kar diya | Key leak ho jayegi | Use .env file and never commit |
| Password hash karna bhool gaye | Database leak ho gayi toh sabki password public | Always use hash_password |
| Token expiry bohot lamba rakha (days) | Security risk | Access token: 15-30 min, refresh token: days |
| Token store karne ke liye localStorage use karna (web) | XSS attacks risk | Use httpOnly cookies or secure storage |
| Refresh token revoke mechanism nahi hai | Logout ke baad bhi token valid rahega | Store refresh tokens in DB, blacklist on logout |
sub field mein email nahi daala | Token validation fail | Always put unique identifier in sub |
| HTTPS nahi use kiya | Token MITM attack se leak | Production mein hamesha HTTPS |
Personal Mistake: Maine ek baar secret key "secret" rakhi aur commit kar di. Kuch din baad kisi ne token forge kar liya. Tab se .env use karta hoon aur .gitignore mein daalta hoon.
11. Best Practices – Production Ready Auth
✅ Use environment variables for secrets:
from dotenv import load_dotenv
import os
load_dotenv()
SECRET_KEY = os.getenv("SECRET_KEY")✅ Set short access token expiry – 15 to 30 minutes
✅ Use refresh tokens stored in database – can revoke on logout
✅ Hash passwords with bcrypt – strong and slow
✅ Use HTTPS in production – never send tokens over HTTP
✅ Implement rate limiting – prevent brute force attacks
✅ Log suspicious activities – multiple failed logins, etc.
✅ Use OAuth2 scopes for permissions: (read, write, admin)
✅ Send token via httpOnly cookie (more secure for web):
from fastapi.responses import JSONResponse
@app.post("/login")
async def login(response: JSONResponse, ...):
# set cookie
response.set_cookie(key="access_token", value=token, httponly=True)12. Resources – Cheat Sheet + Practice Prompts
Cheat Sheet (Copy-Paste Ready)
# ---------- HASHING ----------
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
hashed = pwd_context.hash("password")
verify = pwd_context.verify("password", hashed)
# ---------- JWT TOKEN ----------
from jose import jwt
from datetime import datetime, timedelta
token = jwt.encode({"sub": email, "exp": datetime.utcnow() + timedelta(minutes=30)}, SECRET_KEY)
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
# ---------- DEPENDENCY ----------
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
async def get_current_user(token: str = Depends(oauth2_scheme)):
# decode token, fetch user from DB
return user
@app.get("/me")
async def me(current_user = Depends(get_current_user)):
return current_userPractice Prompts
- Beginner: Basic signup + login + protected
/profileendpoint banao (in-memory storage). - Intermediate: Refresh token implement karo. Ek
/logoutendpoint banao jo refresh token invalidate kare (store in DB blacklist). - Advanced: Role-based access control (RBAC) implement karo –
admin,moderator,user. Different endpoints ke liye different permissions.
13. FAQ
Q1: JWT aur Session authentication mein kya antar hai?
JWT stateless hota hai – server side mein session store nahi karna padta. Session stateful hai – server mein session store karna padta hai. JWT scaling mein easy hai, but revoke karna mushkil.
Q2: Token ko store kahan karein (web client mein)?
localStorage simple hai lekin XSS vulnerable. httpOnly cookie safer hai (cannot be accessed by JavaScript). Mobile apps mein secure storage use karo.
Q3: Token expire hone ke baad automatically refresh kaise karein?
Client har request mein token bhejta hai. Agar 401 aata hai, toh refresh token endpoint call karo and retry original request.
Q4: Kya token mein password ya sensitive data store kar sakte hain?
Token payload easily decode ho sakta hai (base64). Isliye sensitive data (password, credit card) kabhi mat store karo.
Q5: OAuth2PasswordBearer kyun use karte hain?
FastAPI ka built-in helper hai jo Authorization: Bearer <token> header se token extract karta hai. Agar token missing hai toh automatic 401 return karta hai.
Q6: JWT token ko blacklist kaise karein (logout)?
JWT inherently revoke nahi ho sakta. Common approach – maintain a blacklist of token IDs or use short expiry + refresh token revoke.
Q7: Kya mai JWT ke saath websockets use kar sakta hoon?
Haan – websocket connection establish karte time token query parameter ya header mein bhejo, pehle verify karo then connection accept karo.
14. Conclusion
Bahut badhiya! Aapne aaj seekh liya:
✅ FastAPI authentication JWT Hindi mein – complete flow
✅ Password hashing – kabhi plain password nahi
✅ User registration and login endpoints
✅ JWT token generation and verification
✅ Protected routes using Depends(get_current_user)
✅ Refresh token pattern for better UX
Authentication ek essential skill hai – har real-world API mein chahiye. Ab aap secure APIs bana sakte ho.
Aapki aaj ki challenge: Upar diye practice prompts mein se koi ek implement karo (beginner wala bhi chalega). Apna code comment mein share karo – main review karunga.
Next topic kya chahiye?
- FastAPI WebSockets (real-time chat with JWT)?
- FastAPI + Redis Caching?
- FastAPI Background Tasks + Celery?
Comment mein batao!
The Easy Master ke saath secure coding seekhte raho. Happy authenticating! 🔐🚀
Resources
- JWT.io – Introduction to JSON Web Tokens
- FastAPI Security Documentation
- Python JOSE (JWT) Library Docs
- Passlib Bcrypt Tutorial
Additional Resources
- MongoDB Setup – CRUD Operations समझे (Beginner Guide) 2026
- MongoDB Compass से GUI Database Manage करने का आसान तरीका | Beginner Tutorial 2026
- Node.js MongoDB Connection – Mongoose Setup समझे 2026
- MongoDB Data Modeling – Embedded Documents vs References 2026
- MongoDB Indexing – Query Speed बढ़ने करने का आसान तरीका
- MongoDB Aggregation Pipeline – Stages समझे | Practical Examples
- Express MongoDB CRUD – Complete REST API Example
- Mongoose ODM – Schema, Model, and Validation समझे 2026
- MongoDB Atlas – Cloud Database Free में Deploy करें 2026
- JWT Authentication MongoDB – User Login System कैसे बनाएं 2026
- Next.js App Router – Pages Router से क्या बदला? Complete Guide 2026
- Next.js Server Components – ‘use client’ कब और कहां Use करें
- Next.js Routing – Layouts, Dynamic Routes and Nested Routes 2026
- Next.js 16 New Features – Turbopack, Cache Components and proxy.ts
- Next.js Partial Prerendering – Static and Dynamic Content साथ में
- Next.js Authentication – JWT Session Management (App Router) 2026
- Next.js SEO – Metadata API and Image Optimization समझे 2026
- Next.js TypeScript – Full-Stack Type-Safe App कैसे बनाएं
- FastAPI Kya Hai? FastAPI Python Setup Aur Pehla API Hindi 2026
- FastAPI Path Parameters Hindi – शून्य से हीरो तक गाइड 2026
- Pydantic v2 Tutorial Hindi – Data Validation Master 2026
- FastAPI dependency injection Hindi – Code Reuse Ka Magic
- FastAPI Async Await Hindi – Non-Blocking Code 2026
- FastAPI PostgreSQL SQLModel Hindi – Async Guide 2026
Views: 427