creating-a-restful-api-with-fastapi-and-jwt-authentication.html

Creating a RESTful API with FastAPI and JWT Authentication

In today's digital world, creating secure and efficient web applications is paramount. One of the most effective ways to build a robust backend is by developing a RESTful API. FastAPI, a modern Python web framework, simplifies this process while providing out-of-the-box support for JWT (JSON Web Tokens) authentication. In this article, we’ll explore how to create a RESTful API using FastAPI and implement JWT authentication, along with practical coding examples to guide you through each step.

What is FastAPI?

FastAPI is an asynchronous web framework for building APIs with Python 3.7+ based on standard Python type hints. It is designed to be fast (high performance), easy to use, and allows for automatic generation of OpenAPI documentation. FastAPI is particularly popular for its simplicity in creating RESTful APIs and its integration with data validation.

Key Features of FastAPI:

  • Fast: High performance, on par with Node.js and Go.
  • Easy: Simple and intuitive syntax.
  • Automatic Docs: Interactive API documentation generated automatically.
  • Type Checking: Utilizes Python type hints for validation and serialization.

Understanding JWT Authentication

JWT (JSON Web Tokens) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure.

Why Use JWT?

  • Stateless: The server does not need to store session information.
  • Cross-Domain: Can be used across different domains.
  • Scalable: Suitable for microservices architecture.

Setting Up FastAPI

Before we begin coding, ensure you have Python 3.7+ installed. You can create a new FastAPI project by following these steps:

  1. Install FastAPI and a web server (like Uvicorn): bash pip install fastapi[all] uvicorn

  2. Create a new Python file (e.g., main.py).

Step-by-Step: Building a RESTful API

Step 1: Basic FastAPI Setup

Start by creating a simple FastAPI application.

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

Step 2: Adding User Registration and JWT Generation

We will create endpoints for user registration and login, generating JWTs upon successful login.

User Model

First, define a user model using Pydantic.

from pydantic import BaseModel

class User(BaseModel):
    username: str
    password: str

User Registration Endpoint

Now, add a registration endpoint.

users_db = {}

@app.post("/register")
async def register(user: User):
    if user.username in users_db:
        return {"error": "User already exists."}
    users_db[user.username] = user.password
    return {"msg": "User registered successfully."}

Step 3: Implementing JWT Authentication

To implement JWT, you need to install the pyjwt library:

pip install pyjwt

Create JWT Token

Add a function to create a JWT token.

import jwt
import datetime
from fastapi import HTTPException, Depends, status

SECRET_KEY = "your_secret_key"
ALGORITHM = "HS256"

def create_jwt_token(username: str):
    expiration = datetime.datetime.utcnow() + datetime.timedelta(hours=1)
    token = jwt.encode({"exp": expiration, "sub": username}, SECRET_KEY, algorithm=ALGORITHM)
    return token

Login Endpoint

Now, create a login endpoint to authenticate users and return a JWT token.

@app.post("/login")
async def login(user: User):
    stored_password = users_db.get(user.username)
    if not stored_password or stored_password != user.password:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials")

    token = create_jwt_token(user.username)
    return {"access_token": token, "token_type": "bearer"}

Step 4: Protecting Routes with JWT

To protect certain routes, create a dependency that verifies the token.

from fastapi import Security
from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")

def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
    except jwt.PyJWTError:
        raise credentials_exception
    return username

Step 5: Creating a Protected Route

Now, let's create a protected route that requires authentication.

@app.get("/users/me")
async def read_users_me(current_user: str = Depends(get_current_user)):
    return {"msg": f"Hello, {current_user}!"}

Running the FastAPI Application

Run the application using Uvicorn:

uvicorn main:app --reload

Visit http://127.0.0.1:8000/docs to see the automatically generated documentation and test your API endpoints.

Conclusion

In this article, we’ve walked through the steps to create a RESTful API using FastAPI, with JWT authentication to secure your endpoints. FastAPI's ease of use, combined with the stateless nature of JWT, makes it a powerful choice for building modern web applications.

Key Takeaways:

  • FastAPI is an efficient framework for developing APIs.
  • JWT provides a secure way to handle user authentication.
  • The combination of FastAPI and JWT simplifies the implementation of secure APIs.

Now that you have a foundational understanding, you can expand on this by adding features like user roles, password hashing, and more. Happy coding!

SR
Syed
Rizwan

About the Author

Syed Rizwan is a Machine Learning Engineer with 5 years of experience in AI, IoT, and Industrial Automation.