Welcome to Day 11 of our FastAPI Zero to Hero 🚀 series!
Today, we’re stepping into the world of authentication and route protection — a crucial part of any production-ready app.
Think of this as putting a lock on your house and giving keys only to the right people.
🔒 Why Authentication Matters?
Think of it as creating a blog similar to Dev.to. You would prefer that no one:
- Articles published on your behalf 😱
- Get to your private drafts 📝
- Get rid of your posts 🚫
A login system is required that:
- Verifies the user
- Provides a secure token
- Every request is verified using this token.
- Guards delicate pathways
🧠 Concepts We’ll Cover
- What is Basic Auth vs OAuth2 Password Flow
- What is a JWT (JSON Web Token) and why use it
- How to:
- Create a login endpoint
- Issue and verify JWTs
- Protect routes using tokens
🔐 What is Basic Auth?
Every request sent via Basic Auth includes the username and password, which are Base64-encoded (not encrypted!). It is simple, however unless you use HTTPS, it is not secure for production.
It's convenient, but it's unsafe, like writing your ATM PIN on the back of your debit card.
🔐 What is OAuth2 Password Flow?
An industry-standard authorisation protocol is OAuth2.
First-party apps, such as your own web or mobile app, employ a particular kind called Password Flow, in which the user sends their username and password once in order to receive a JWT token.
This token is sent with every request and is stored client-side.
Consider the token as a movie ticket — you can roam the theatre after being validated at the gate (API).
🧾 What is JWT (JSON Web Token)?
A JWT is a compact, self-contained token that contains information like:
- User ID
- Expiry time
- Issuer
It’s signed (not encrypted), so it can be verified by the server using a secret key.
🔐 Libraries Used for Authentication in FastAPI
Let's break down two essential libraries we use to handle authentication securely in FastAPI.
📦 1. python-jose
python-jose
is a Python implementation of the JOSE (JavaScript Object Signing and Encryption) standard. It provides support for JWT (JSON Web Token) handling.
✅ Why We Use It
JWT token encoding: Generate access tokens with user data contained.
Decoding JWT tokens: When users get access to protected endpoints, they must read and confirm the token.
Signing tokens: Secure tokens that use techniques like HS256
and a secret key.
Consider it the digital signature tool for the identity cards (tokens) in your app.
🔐 2. passlib[bcrypt]
passlib
is a comprehensive password hashing library for Python.
- When installed with the
[bcrypt]
extra ("passlib[bcrypt]"
), it enables support for the bcrypt algorithm — one of the most secure and widely recommended password hashing methods.
✅ Why We Use It
- Secure password storage: Instead of storing plain text passwords, we hash them.
- Password verification: Compare hashed input with stored password hashes.
- Industry best practices: Used by major web frameworks and recommended for production.
In real-world applications, never store plain text passwords. Use
passlib
withbcrypt
to hash and verify them securely.
🛠 Installation
⚠️ On some shells like Zsh, square brackets need to be quoted!
pip3 install python-jose "passlib[bcrypt]"
📁 Project Structure
Here's how your FastAPI authentication project is organised:
authentication/
│
├── main.py # FastAPI app with login and protected route
└── auth.py # Utility for JWT encoding/decoding
🔹 main.py
- Defines your FastAPI app
- Implements the
/token
login route - Implements the
/dashboard
protected route - Verifies tokens using dependencies
🔹 auth.py
- Contains helper functions to:
- Create JWT tokens
- Decode and verify tokens
- Uses
python-jose
for secure token signing
This modular structure keeps your code clean, scalable, and production-ready. 💡
🔐 auth.py
– JWT Utility
This file handles JWT creation and decoding using python-jose
.
from datetime import datetime, timedelta
from jose import JWTError, jwt
# In production, keep this secret in environment or AWS Secrets Manager
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
def create_access_token(data: dict, expires_delta=None):
to_encode = data.copy()
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
def decode_token(token: str):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return payload.get("sub")
except JWTError:
return None
🚀 main.py
– FastAPI App
This is the main application file where we define our FastAPI routes, handle user authentication, and protect endpoints using JWT tokens.
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from auth import create_access_token, decode_token
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
app = FastAPI()
oauth2_scheme = HTTPBearer()
# In-memory fake database
fake_users_db = {
"utkarsh": {
"username": "utkarsh",
"password": "test123", # In real life, use hashed passwords!
}
}
def authenticate_user(username: str, password: str):
user = fake_users_db.get(username)
if not user or user["password"] != password:
return None
return user
@app.post("/token")
def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token = create_access_token(data={"sub": user["username"]})
return {"access_token": access_token, "token_type": "bearer"}
def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(oauth2_scheme)):
token = credentials.credentials
username = decode_token(token)
if not username:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid token",
)
return username
@app.get("/dashboard")
def read_dashboard(current_user: str = Depends(get_current_user)):
return {"message": f"Hello, {current_user}! Welcome to your dashboard."}
▶️ How to Run the App
Follow these simple steps to run the FastAPI app locally:
🚀 Step 1: Start the FastAPI Server
Run the app using Uvicorn:
uvicorn main:app --host 0.0.0.0 --reload --port 9001
🌐 Step 2: Access Swagger UI
Once the FastAPI server is running, open your browser and navigate to:
This will launch the interactive Swagger UI, where you can:
- 🔐 Log in using the
/token
endpoint - 🛡️ Authorize yourself with the JWT token
- 🚪 Access the protected
/dashboard
route
Swagger UI provides a friendly interface to test your APIs without writing any frontend code.
🔑 Testing the Flow
Follow these steps to test authentication using Swagger UI:
✅ Step 1: Login and Get Token
- In Swagger UI, scroll to the
/token
endpoint. - Click "Try it out".
- Enter the following credentials: username: utkarsh password:test123
- Click "Execute".
- In the response, copy the value of
access_token
.
🔐 Step 2: Access Protected Route
- Scroll to the
/dashboard
endpoint. - Click the "Authorize" button at the top-right corner of Swagger UI.
- In the popup, enter: Bearer
Click "Authorize" and then "Close".
Now click "Try it out" under
/dashboard
, then click "Execute".
You should receive a response like:
{
"message": "Hello,utkarsh! Welcome to your dashboard."
}
🧠 Real-World Analogy
This authentication pattern is similar to how Dev.to, Twitter, or any secure app works:
- 🧑💻 You log in once using your credentials
- 🪪 You receive a secure JWT token
- 🔐 This token is included in all future requests to prove your identity
The backend verifies the token on every request, and based on it:
- ✅ Lets you access your private data
- ✏️ Allows you to edit your content
- 🛑 Blocks unauthorized access
With this setup, you can now build personalized dashboards, post editors, and even admin panels — all securely protected using JWTs.
✅ Summary
Let's wrap up what we learned today:
- 🚀 FastAPI makes it incredibly simple to create secure login systems
- 🔐 OAuth2 Password Flow is ideal for first-party apps (web or mobile)
- 🪙 JWT (JSON Web Tokens) are stateless and scalable — no server-side sessions needed
- 🛡️ You now know how to:
- Create a login endpoint
- Generate and verify JWTs
- Protect any route in your API using
Depends()
You're one step closer to building a production-grade authentication system in FastAPI!
🙏 Credits
Huge thanks to the FastAPI Official Documentation by Sebastián Ramírez (@tiangolo) — the best place to learn and explore everything about FastAPI.
👨💻 About Me
Hey there! I’m Utkarsh Rastogi, an AWS Community Builder and passionate cloud-native enthusiast who loves building scalable backend systems and sharing knowledge with the community.
🔗 Connect with me: Utkarsh Rastogi
💬 Share Your Thoughts – I'd Love Your Feedback!
If you enjoyed today's post or learned something new, I'd truly appreciate it if you leave a comment or share your thoughts 👇
Your feedback, questions, or even a quick “🔥 Loved this!” keeps me motivated to continue this journey and share more in the upcoming #FastAPIDaily posts.
✅ What did you find most helpful?
✅ Anything you'd like explained in the next part?
✅ Suggestions for improvement? I’m all ears! 🙌
Let’s grow and learn together — one FastAPI day at a time 🚀
Top comments (0)