Authentication and OAuth2
Implementing OAuth2 with Passwords and handling JWTs in FastAPI.
🧑🏫 Sabse pehle — simple mein samjho#
Authentication ke fundamentals wahi hain jo Node.js mein the: Password hash karo (Passlib library use karke) aur login ke time ek JWT token do (PyJWT use karke). FastAPI is process ko thoda aur standardize kar deta hai apne built-in OAuth2 tools ke sath. Jab tum FastAPI ka OAuth2 dependency use karte ho, to tumhara Swagger UI /docs page directly ek "Authorize" button dikhane lagta hai! Tum wahi se login karke saare protected routes test kar sakte ho bina Postman ke!
The FastAPI Security Module#
FastAPI provides standard security schemes out of the box. We will use OAuth2PasswordBearer, which simply tells FastAPI: "Look for an Authorization header that contains the word Bearer followed by a token."
from fastapi import Depends, FastAPI
from fastapi.security import OAuth2PasswordBearer
app = FastAPI()
# We specify the URL where the client should send their username/password to get the token
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
# Any route that depends on oauth2_scheme will automatically reject requests without a token!
@app.get("/items/")
async def read_items(token: str = Depends(oauth2_scheme)):
return {"token_provided": token}
The Full Auth Flow#
Here is a simplified overview of how to build a complete Auth system in FastAPI. You need two external libraries: passlib (for hashing) and PyJWT (for token generation).
1. Generating a Token on Login#
The login endpoint must accept a specific form format (OAuth2 standards).
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
import jwt # (PyJWT)
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
# 1. Fetch user from DB using form_data.username
# 2. Hash form_data.password and compare it using passlib
if not valid_password:
raise HTTPException(status_code=400, detail="Incorrect username or password")
# 3. Create the JWT
token_data = {"sub": form_data.username} # 'sub' is standard for Subject (User)
token = jwt.encode(token_data, "SECRET_KEY", algorithm="HS256")
# 4. Return it strictly in this JSON format
return {"access_token": token, "token_type": "bearer"}
2. A Dependency to Verify Tokens#
We create a dependency that extracts the token, verifies its signature, and returns the current user.
async def get_current_user(token: str = Depends(oauth2_scheme)):
try:
# Verify the signature and decode the payload
payload = jwt.decode(token, "SECRET_KEY", algorithms=["HS256"])
username = payload.get("sub")
if username is None:
raise HTTPException(status_code=401, detail="Invalid auth credentials")
except jwt.PyJWTError:
raise HTTPException(status_code=401, detail="Token has expired or is invalid")
# Fetch user from DB and return it
# user = db.query(User).filter(User.username == username).first()
return {"username": username}
3. Protecting Routes#
Now, any route that needs protection just injects get_current_user.
@app.get("/users/me")
async def read_users_me(current_user: dict = Depends(get_current_user)):
# This only runs if the token was perfectly valid!
return {"status": "authenticated", "user": current_user}