2-how-to-set-up-a-secure-api-with-fastapi-and-oauth2.html

How to Set Up a Secure API with FastAPI and OAuth2

In today’s digital landscape, securing your application’s API is more critical than ever. FastAPI, a modern web framework for building APIs with Python, provides an excellent way to create secure endpoints using OAuth2. This guide will walk you through the process of setting up a secure API with FastAPI, leveraging OAuth2 for authentication.

What is FastAPI?

FastAPI is a high-performance web framework that allows developers to build APIs quickly and efficiently. With features like automatic data validation, interactive API documentation, and asynchronous support, FastAPI is a popular choice for modern web applications. Its built-in support for OAuth2 makes it particularly appealing for developers looking to implement secure authentication.

Understanding OAuth2

OAuth2 is an authorization framework that enables third-party services to exchange web resources on behalf of a user. It allows applications to obtain limited access to user accounts without exposing passwords. The key components of OAuth2 include:

  • Authorization Server: Issues access tokens after authenticating users.
  • Resource Server: Hosts the protected resources and validates access tokens.
  • Client: The application requesting access to the user's data.
  • Resource Owner: The user who owns the data.

Use Cases for FastAPI and OAuth2

  • User Authentication: Allow users to authenticate via third-party services like Google or Facebook.
  • Microservices: Secure communication between microservices using OAuth2 tokens.
  • Mobile Applications: Protect sensitive user data in mobile apps.

Setting Up FastAPI with OAuth2

Prerequisites

Before diving into code, ensure you have the following installed:

  • Python 3.6 or higher
  • FastAPI
  • Uvicorn (ASGI server)
  • A database (like SQLite for this example)
  • passlib for password hashing

You can install the necessary packages with:

pip install fastapi uvicorn[standard] passlib[bcrypt]

Step 1: Create a Basic FastAPI Application

First, create a file named main.py. This file will serve as the foundation for our API.

from fastapi import FastAPI

app = FastAPI()

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

Run the application with Uvicorn:

uvicorn main:app --reload

Navigate to http://127.0.0.1:8000 to see your API in action.

Step 2: Implement User Authentication

Next, we’ll create a simple user model and implement authentication logic. For demonstration purposes, we’ll use an in-memory store for users.

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from passlib.context import CryptContext

# User model
class User(BaseModel):
    username: str
    email: str

# User database (for demonstration purposes)
fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "$2b$12$EIXN1eJ4FJ0L6FzYy3uU5e4TtH5L4r1M5bD3h1jX0U1e5j.UzWy8u",
        "disabled": False,
    }
}

# Password hashing context
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

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

def get_user(db, username: str):
    if username in db:
        user_dict = db[username]
        return User(**user_dict)

# Authentication endpoint
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    user = get_user(fake_users_db, form_data.username)
    if not user or not verify_password(form_data.password, user.hashed_password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return {"access_token": user.username, "token_type": "bearer"}

Step 3: Protect Routes with OAuth2

Now that we have the login functionality, let's secure an API endpoint. We will create a protected route that requires authentication.

from fastapi import Security

@app.get("/users/me")
async def read_users_me(token: str = Depends(oauth2_scheme)):
    user = get_user(fake_users_db, token)
    if user is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid authentication credentials",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return user

Step 4: Testing the API

You can test the API using tools like Postman or directly through the interactive API documentation provided by FastAPI at http://127.0.0.1:8000/docs.

  1. Obtain the Token:
  2. Send a POST request to http://127.0.0.1:8000/token with form data including username and password.

  3. Access Protected Route:

  4. Use the token received in the previous step to access http://127.0.0.1:8000/users/me by including it in the Authorization header as a Bearer token.

Troubleshooting Common Issues

  • Invalid Credentials: Ensure that the username and password are correct. The password must match the hashed version stored in your database.
  • Token Expiry: Implement token expiry handling for better security if your application requires it.

Conclusion

Setting up a secure API using FastAPI and OAuth2 is a straightforward process. With just a few lines of code, you can protect your API endpoints and manage user authentication efficiently. FastAPI’s intuitive design and powerful features make it an excellent choice for building modern web applications.

By following this guide, you now have a solid foundation for a secure API. Feel free to expand upon this basic example by integrating with a real database, adding token expiration, or implementing user roles for more complex applications. 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.