setting-up-a-secure-api-with-fastapi-and-oauth2-authentication.html

Setting Up a Secure API with FastAPI and OAuth2 Authentication

In today's digital landscape, securing your API is more crucial than ever. With the rise of data breaches and cybersecurity threats, developers must implement robust authentication mechanisms. FastAPI, a modern web framework for building APIs with Python, offers an excellent foundation for developing secure applications. In this article, we will explore how to set up a secure API using FastAPI combined with OAuth2 authentication, one of the most widely used protocols for securing APIs.

What is FastAPI?

FastAPI is a high-performance web framework designed for building APIs quickly and efficiently. It is built on top of Starlette for the web parts and Pydantic for the data parts. FastAPI is known for its speed, ease of use, and automatic generation of OpenAPI documentation. It supports asynchronous programming, making it suitable for handling high-performance applications.

Understanding OAuth2 Authentication

OAuth2 is a widely adopted authorization framework that allows third-party applications to access a user's resources without exposing their credentials. OAuth2 provides various flows for different scenarios, but in this article, we will focus on the Password Flow, which is suitable for user authentication.

Key Concepts of OAuth2

  • Authorization Server: The server that issues access tokens.
  • Resource Owner: The user who owns the data and grants access.
  • Client Application: The application requesting access to the user's resources.
  • Access Token: A token that the client uses to access protected resources.

Use Cases for FastAPI with OAuth2

  • Microservices: Secure APIs in a microservices architecture.
  • Single Page Applications (SPAs): Authenticate users for front-end applications.
  • Mobile Applications: Provide secure API access to mobile clients.

Setting Up FastAPI with OAuth2 Authentication

Step 1: Install Required Libraries

To get started, you will need to install FastAPI and a server such as Uvicorn. Additionally, install python-jose for handling JWT tokens.

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

Step 2: Create the FastAPI Application

Create a new Python file, main.py, and start by importing the necessary libraries.

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from typing import Optional
from passlib.context import CryptContext
import jwt
import datetime

app = FastAPI()

Step 3: Define User Models and Password Hashing

Create user models and a password hashing utility.

class User(BaseModel):
    username: str
    email: str
    full_name: str = None
    disabled: bool = None

class UserInDB(User):
    hashed_password: str

# Password hashing
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

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

def get_password_hash(password):
    return pwd_context.hash(password)

Step 4: Implement OAuth2 Password Flow

Set up the OAuth2PasswordBearer and create a fake database for demonstration purposes.

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

# Simulated database
fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": get_password_hash("secret"),
        "disabled": False,
    }
}

def fake_decode_token(token):
    return fake_users_db.get(token)

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

Step 5: Create Token Generation Logic

Implement the logic for creating JWT tokens.

SECRET_KEY = "your_secret_key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

def create_access_token(data: dict, expires_delta: Optional[datetime.timedelta] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.datetime.utcnow() + expires_delta
    else:
        expire = datetime.datetime.utcnow() + datetime.timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

Step 6: Implement the Login Route

Create a route for user login that issues a token.

@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"},
        )
    access_token_expires = datetime.timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(data={"sub": user.username}, expires_delta=access_token_expires)
    return {"access_token": access_token, "token_type": "bearer"}

Step 7: Protect Routes with OAuth2

Create a protected route that requires authentication.

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

Step 8: Running the Application

To run the application, use Uvicorn:

uvicorn main:app --reload

Step 9: Testing the API

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

  1. Request a Token:
  2. POST to /token with form data: username and password.
  3. Access Protected Route:
  4. Use the token returned from the previous step to access /users/me.

Conclusion

Securing your API with FastAPI and OAuth2 is a straightforward process that significantly enhances the security of your applications. By following the steps outlined in this article, you can implement a robust authentication system that protects your users' data. FastAPI's simplicity and performance make it an excellent choice for developing secure APIs. Start building your API today and ensure your users are safe from unauthorized access!

SR
Syed
Rizwan

About the Author

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