CS504070 - FastAPI Tutorials
  • 🧩CS504070 - FastAPI Tutorials
  • 🔎Unit 1: Python Type Hint
  • ⚙️Unit 2: Pydantic
  • 🔃Unit 3: Concurrency
  • 💾Unit 4: Install FastAPI
  • 🍉Unit 5: Hello World!
  • 🍌Unit 6: Path Parameters
  • 🍋Unit 7: Query Parameters
  • 🍊Unit 8: Request Body
  • 🍐Unit 9: Query Parameters and Validations
  • 🍎Unit 10: Path Parameters and Validations
  • 🍏Unit 11: Multiple Parameters
  • 🍇Unit 12: Request Body - List Fields and Nested Models
  • 🍓Unit 13: Data Types
  • 🍪Unit 14: Cookie Parameters
  • 🫐Unit 15: Header Parameters
  • 🍈Unit 16: Response Model - Return Type
  • 🍒Unit 17: Additional Models
  • 🥑Unit 18: Implementing JWT Authentication with FastAPI
  • ⚙️Appendix A
  • 🍭Appendix B
Powered by GitBook
On this page
  • Introduction
  • What is JWT?
  • Advantages of JWT
  • Implementing JWT in FastAPI
  • Step-by-step Implementation:
  • Testing the Application
  • Exercises

Unit 18: Implementing JWT Authentication with FastAPI

Introduction

JWT (JSON Web Token) is a compact, secure means for transmitting information as a JSON object. It's commonly used for authentication and authorization purposes.

What is JWT?

JWT is composed of three parts:

  • Header: Specifies the algorithm used to sign the token.

  • Payload: Contains claims, including user details and token expiration.

  • Signature: Used to verify token authenticity.

Advantages of JWT

  • Stateless authentication

  • Secure information exchange

  • Easy integration with frontend frameworks

Implementing JWT in FastAPI

Step-by-step Implementation:

Step 1: Install Dependencies

pip install fastapi uvicorn python-jose[cryptography] passlib[bcrypt]

Step 2: Basic JWT Setup

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm, OAuth2PasswordBearer
from jose import JWTError, jwt
from passlib.context import CryptContext

SECRET_KEY = "your_secret_key"
ALGORITHM = "HS256"
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

app = FastAPI()

# Dummy user
fake_users_db = {
    "user@example.com": {
        "username": "user@example.com",
        "hashed_password": pwd_context.hash("password123")
    }
}

def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)

def authenticate_user(username: str, password: str):
    user = fake_users_db.get(username)
    if not user or not verify_password(password, user["hashed_password"]):
        return False
    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)
    token_data = {"sub": user["username"]}
    access_token = jwt.encode(token_data, SECRET_KEY, algorithm=ALGORITHM)
    return {"access_token": access_token, "token_type": "bearer"}

@app.get("/protected")
def read_protected(token: str = Depends(oauth2_scheme)):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username = payload.get("sub")
        if username is None:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
    except JWTError:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
    return {"Hello": username}

Testing the Application

You can test the above program with Postman, or you can use the following testing approach with pytest and httpx.

Create a test file test_jwt.py:

import pytest
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_login_and_protected_endpoint():
    response = client.post("/token", data={"username": "user@example.com", "password": "password123"})
    assert response.status_code == 200
    token = response.json()["access_token"]

    protected_response = client.get("/protected", headers={"Authorization": f"Bearer {token}"})
    assert protected_response.status_code == 200
    assert protected_response.json() == {"Hello": "user@example.com"}

def test_invalid_token():
    protected_response = client.get("/protected", headers={"Authorization": "Bearer invalidtoken"})
    assert protected_response.status_code == 401

Run the tests with:

pytest test_jwt.py

Exercises

  1. Extend JWT Payload: Modify the JWT to include user roles (admin, user) and restrict access to specific endpoints based on these roles.

  2. Implement Token Expiration: Set JWT expiration to 30 minutes and handle token refresh.

  3. JWT Blacklisting: Implement JWT token blacklisting using a Redis cache to enable immediate token revocation.

  4. Testing and Validation: Write comprehensive unit tests using Pytest to test JWT authentication scenarios, including edge cases such as invalid and expired tokens.

PreviousUnit 17: Additional ModelsNextAppendix A

Last updated 1 month ago

🥑
Page cover image