DEV Community

Cover image for Day 11 : FastAPI Auth: Login with JWT & Route Protection
Utkarsh Rastogi
Utkarsh Rastogi

Posted on

1 1

Day 11 : FastAPI Auth: Login with JWT & Route Protection

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:

  1. Verifies the user
  2. Provides a secure token
  3. Every request is verified using this token.
  4. 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 with bcrypt to hash and verify them securely.


🛠 Installation

⚠️ On some shells like Zsh, square brackets need to be quoted!

pip3 install python-jose "passlib[bcrypt]"
Enter fullscreen mode Exit fullscreen mode

📁 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
Enter fullscreen mode Exit fullscreen mode

🚀 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."}
Enter fullscreen mode Exit fullscreen mode

▶️ 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
Enter fullscreen mode Exit fullscreen mode

🌐 Step 2: Access Swagger UI

Once the FastAPI server is running, open your browser and navigate to:

👉 http://localhost:9001/docs

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

  1. In Swagger UI, scroll to the /token endpoint.
  2. Click "Try it out".
  3. Enter the following credentials: username: utkarsh password:test123
  4. Click "Execute".
  5. In the response, copy the value of access_token.

Input1

Output1


🔐 Step 2: Access Protected Route

  1. Scroll to the /dashboard endpoint.
  2. Click the "Authorize" button at the top-right corner of Swagger UI.
  3. In the popup, enter: Bearer

Token

  • Click "Authorize" and then "Close".

  • Now click "Try it out" under /dashboard, then click "Execute".

Output

You should receive a response like:

{
"message": "Hello,utkarsh! Welcome to your dashboard."
}
Enter fullscreen mode Exit fullscreen mode

🧠 Real-World Analogy

This authentication pattern is similar to how Dev.to, Twitter, or any secure app works:

  1. 🧑‍💻 You log in once using your credentials
  2. 🪪 You receive a secure JWT token
  3. 🔐 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 🚀


You Know That Your Mobile App Needs Security. Here\

You Know That Your Mobile App Needs Security. Here's How to Get Started

Mobile apps have become a cornerstone of modern life. With billions of users, they have become a prime target for attackers. By implementing strong mobile app security, organizations can prevent IP theft, revenue loss, and an erosion of user trust.

Read the guide

Top comments (0)

You Know That Your Mobile App Needs Security. Here\

You Know That Your Mobile App Needs Security. Here's How to Get Started

Mobile apps have become a cornerstone of modern life. With billions of users, they have become a prime target for attackers. By implementing strong mobile app security, organizations can prevent IP theft, revenue loss, and an erosion of user trust.

Read the guide

👋 Kindness is contagious

Explore this insightful write-up embraced by the inclusive DEV Community. Tech enthusiasts of all skill levels can contribute insights and expand our shared knowledge.

Spreading a simple "thank you" uplifts creators—let them know your thoughts in the discussion below!

At DEV, collaborative learning fuels growth and forges stronger connections. If this piece resonated with you, a brief note of thanks goes a long way.

Okay