DEV Community

Cover image for DIY JWT Authentication in FastAPI Using Only Python
Leapcell
Leapcell

Posted on

2 1 1 1 1

DIY JWT Authentication in FastAPI Using Only Python

Image description

Leapcell: The Best of Serverless Web Hosting

Implementing Authentication with JWT in FastAPI

Introduction

In modern web application development, authentication is a crucial part of ensuring system security. JSON Web Token (JWT), as an open standard based on JSON (RFC 7519), is widely used in single sign-on (SSO) scenarios for distributed sites due to its compactness and security. FastAPI is a high-performance web framework based on Python. This article will introduce how to use JWT for authentication in FastAPI, combined with the given JWT implementation code.

Basics of JWT

What is JWT?

JSON Web Token (JWT) is designed to transmit claims between network application environments. It is compact and secure, especially suitable for single sign-on scenarios in distributed sites. JWT claims are often used to transmit the authenticated user identity information between the identity provider and the service provider to obtain resources from the resource server, and can also add other claim information required by business logic. This token can be directly used for authentication or encrypted.

Composition of JWT

JWT consists of three segments of information:

  • Header: Usually declares the file type and encryption algorithm.
  • Payload: Records the data to be transmitted in JSON format.
  • Signature: A signature used for verification.

base64UrlEncode Method

When generating a JWT, the base64UrlEncode method is used for the signature. The basic functions of this method are as follows:

  1. Input a UTF-8 encoded string s1.
  2. Encode the string s1 using base64 to get the string s2.
  3. If there are equal signs at the end of s2, remove all equal signs at the end.
  4. If there are plus signs (+) in s2, replace all plus signs with minus signs (-).
  5. If there are slashes (/) in s2, replace all slashes with underscores (_).

The following is the Python code to implement this method:

import hmac
import base64
from hashlib import sha256
from urllib import parse as urlp

def b64url(str1):
    if type(str1) == str:
        return str(base64.b64encode(str1.encode('utf-8')), encoding="utf-8").strip('=').replace('+', '-').replace('/', '_')
    elif type(str1) == bytes:
        return str(base64.b64encode(str1), encoding="utf-8").strip('=').replace('+', '-').replace('/', '_')
    else:
        raise TypeError("The type of given argument must be string or bytes")
Enter fullscreen mode Exit fullscreen mode

Generating a JWT Encrypted with HS256

The following is the code to generate a JWT encrypted with HS256 using the above b64url function:

# Enter Your Infomation Here ...
header = b64url('{"alg":"HS256","typ":"JWT"}')
payload = b64url('{"sub":"1234567890","name":"John Doe","iat":1516239022}')
secret = 'happynewyear'.encode('utf-8')
# ###

sig = b64url(hmac.new(
    secret, (header + '.' + payload).encode('utf-8'), digestmod=sha256
).digest())

jwt = header + '.' + payload + '.' + sig
print(jwt)
Enter fullscreen mode Exit fullscreen mode

Integrating JWT in FastAPI

Installing Dependencies

Before you start, you need to install fastapi and uvicorn. You can use the following command to install them:

pip install fastapi uvicorn
Enter fullscreen mode Exit fullscreen mode

Implementation Steps

1. Creating a FastAPI Application

from fastapi import FastAPI, HTTPException, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import hmac
import base64
from hashlib import sha256

app = FastAPI()

# Define the b64url function
def b64url(str1):
    if type(str1) == str:
        return str(base64.b64encode(str1.encode('utf-8')), encoding="utf-8").strip('=').replace('+', '-').replace('/', '_')
    elif type(str1) == bytes:
        return str(base64.b64encode(str1), encoding="utf-8").strip('=').replace('+', '-').replace('/', '_')
    else:
        raise TypeError("The type of given argument must be string or bytes")

# Secret key
SECRET_KEY = 'happynewyear'.encode('utf-8')

# Function to generate JWT
def generate_jwt():
    header = b64url('{"alg":"HS256","typ":"JWT"}')
    payload = b64url('{"sub":"1234567890","name":"John Doe","iat":1516239022}')
    sig = b64url(hmac.new(
        SECRET_KEY, (header + '.' + payload).encode('utf-8'), digestmod=sha256
    ).digest())
    return header + '.' + payload + '.' + sig

# Function to verify JWT
def verify_jwt(token: str):
    parts = token.split('.')
    if len(parts) != 3:
        return False
    header, payload, received_sig = parts
    new_sig = b64url(hmac.new(
        SECRET_KEY, (header + '.' + payload).encode('utf-8'), digestmod=sha256
    ).digest())
    return new_sig == received_sig

# Define the JWT verification dependency
class JWTBearer(HTTPBearer):
    def __init__(self, auto_error: bool = True):
        super(JWTBearer, self).__init__(auto_error=auto_error)

    async def __call__(self, request):
        credentials: HTTPAuthorizationCredentials = await super(JWTBearer, self).__call__(request)
        if credentials:
            if not credentials.scheme == "Bearer":
                raise HTTPException(status_code=401, detail="Invalid authentication scheme.")
            if not verify_jwt(credentials.credentials):
                raise HTTPException(status_code=401, detail="Invalid or expired token.")
            return credentials.credentials
        else:
            raise HTTPException(status_code=401, detail="Invalid authorization code.")

Enter fullscreen mode Exit fullscreen mode

2. Creating a Login Interface

# Simulated login interface
@app.post("/login")
def login():
    token = generate_jwt()
    return {"access_token": token, "token_type": "bearer"}

Enter fullscreen mode Exit fullscreen mode

3. Creating a Protected Interface

# Protected interface
@app.get("/protected", dependencies=[Depends(JWTBearer())])
def protected_route():
    return {"message": "This is a protected route."}

Enter fullscreen mode Exit fullscreen mode

Running the Application

Save the above code as main.py, and then run the following command in the terminal to start the application:

uvicorn main:app --reload
Enter fullscreen mode Exit fullscreen mode

Testing the Interfaces

  • Login Interface: Use tools like curl or Postman to send a POST request to http://localhost:8000/login, and it will return a JWT.
curl -X POST http://localhost:8000/login
Enter fullscreen mode Exit fullscreen mode
  • Protected Interface: Use the returned JWT to send a GET request to http://localhost:8000/protected, and add Authorization: Bearer <your_token> to the request header.
curl -X GET http://localhost:8000/protected -H "Authorization: Bearer <your_token>"
Enter fullscreen mode Exit fullscreen mode

Conclusion

Through the above steps, you have learned how to use JWT for authentication in FastAPI. JWT provides a secure and convenient way to manage user identities, making authentication between distributed systems more efficient. In practical applications, you can adjust the generation and verification logic of JWT according to your needs, such as adding an expiration time, customizing claims, etc.

Leapcell: The Best of Serverless Web Hosting

Finally, I would like to recommend a platform that is most suitable for deploying Python services: Leapcell

Image description

🚀 Build with Your Favorite Language

Develop effortlessly in JavaScript, Python, Go, or Rust.

🌍 Deploy Unlimited Projects for Free

Only pay for what you use—no requests, no charges.

⚡ Pay-as-You-Go, No Hidden Costs

No idle fees, just seamless scalability.

Image description

📖 Explore Our Documentation

🔹 Follow us on Twitter: @LeapcellHQ

Quadratic AI

Quadratic AI – The Spreadsheet with AI, Code, and Connections

  • AI-Powered Insights: Ask questions in plain English and get instant visualizations
  • Multi-Language Support: Seamlessly switch between Python, SQL, and JavaScript in one workspace
  • Zero Setup Required: Connect to databases or drag-and-drop files straight from your browser
  • Live Collaboration: Work together in real-time, no matter where your team is located
  • Beyond Formulas: Tackle complex analysis that traditional spreadsheets can't handle

Get started for free.

Watch The Demo 📊✨

Top comments (0)

Jetbrains Survey

Calling all developers!

Participate in the Developer Ecosystem Survey 2025 and get the chance to win a MacBook Pro, an iPhone 16, or other exciting prizes. Contribute to our research on the development landscape.

Take the survey