Authentication and Authorization in FastAPI: Securing Your API Endpoints

Understanding Authentication and Authorization in FastAPI FastAPI is an emerging web framework designed for building APIs with Python 3.7+ based on standard Python type hints. When developing applications, especially APIs that involve sensitive user data,

Written by: Leo Nguyen

Published on: January 7, 2026

Understanding Authentication and Authorization in FastAPI

FastAPI is an emerging web framework designed for building APIs with Python 3.7+ based on standard Python type hints. When developing applications, especially APIs that involve sensitive user data, understanding authentication and authorization is critical. These two terms are often used interchangeably but represent different concepts in API security.

What is Authentication?

Authentication is the process of verifying the identity of a user who is trying to access your system. In an API context, it requires users to provide some credentials, such as a username and password. FastAPI naturally supports various authentication methods, including Basic Authentication, OAuth2, and others.

Basic Authentication in FastAPI

Basic Authentication is one of the simplest ways to secure an API. The client sends an Authorization header with the credentials (username and password) encoded in Base64.

To implement Basic Authentication in FastAPI, you can do the following:

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials

app = FastAPI()
security = HTTPBasic()

def authenticate(credentials: HTTPBasicCredentials = Depends(security)):
    valid_username = "user"
    valid_password = "password"

    if credentials.username != valid_username or credentials.password != valid_password:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid credentials",
            headers={"WWW-Authenticate": "Basic"},
        )
    return credentials.username

@app.get("/secure-data")
def get_secure_data(username: str = Depends(authenticate)):
    return {"data": "This is secured data", "user": username}

In this example, when a user tries to access /secure-data, they must provide the correct username and password. If not, they receive a 401 Unauthorized response.

What is Authorization?

Authorization, on the other hand, is about determining what an authenticated user is allowed to do, such as accessing certain resources or performing specific actions. FastAPI makes it straightforward to implement authorization checks for your endpoints.

Role-Based Access Control (RBAC)

RBAC is a popular method for implementing authorization in web applications. In FastAPI, you can create decorators for your endpoint functions to check user roles.

Here’s a basic implementation of RBAC:

from typing import List
from fastapi import FastAPI, Depends, HTTPException, status

app = FastAPI()

fake_users_db = {
    "admin": {"password": "admin_pass", "role": "admin"},
    "user": {"password": "user_pass", "role": "user"},
}

def get_current_user(credentials: HTTPBasicCredentials = Depends(security)):
    user = fake_users_db.get(credentials.username)
    if not user or user["password"] != credentials.password:
        raise HTTPException(status_code=401, detail="Invalid credentials")
    return credentials.username, user["role"]

def require_role(role: str):
    def role_checker(user_role: str = Depends(get_current_user)):
        if user_role[1] != role:
            raise HTTPException(status_code=403, detail="Not enough permissions")
        return user_role[0]
    return role_checker

@app.get("/admin-data")
def get_admin_data(username: str = Depends(require_role("admin"))):
    return {"data": "This is admin data", "user": username}

Here, we create a get_current_user function to validate users and retrieve their roles. The require_role decorator checks if the user has the necessary role to access certain endpoints.

OAuth2 with Password Flow

If you want to implement a more sophisticated authentication method, OAuth2 is often the preferred choice. FastAPI includes built-in support for OAuth2 with Password Flow.

To set up OAuth2, you generally follow these steps:

  1. Create Token Generation Logic: Use the OAuth2PasswordBearer to handle token generation.
  2. Secure Your Endpoints: Use Depends for authentication when accessing protected resources.

Here’s a sample implementation:

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

app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

fake_users_db = {
    "user": {
        "username": "user",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": pwd_context.hash("user_pass"),
        "disabled": False,
    }
}

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:
        return db[username]

def authenticate_user(db, username: str, password: str):
    user = get_user(db, username)
    if not user or not verify_password(password, user['hashed_password']):
        return False
    return user

@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        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"}

@app.get("/users/me")
async def read_users_me(token: str = Depends(oauth2_scheme)):
    return {"token": token}

This example demonstrates a simple token-based authentication system where users can log in and receive an access token for subsequent requests.

Securing Static Files

When your FastAPI application serves static files, it’s vital to handle authentication and authorization appropriately, even for static assets.

You can achieve this by wrapping your static file routes with authentication logic. FastAPI lets you mount static directories using the StaticFiles class.

from fastapi.staticfiles import StaticFiles

app.mount("/static", StaticFiles(directory="static"), name="static")

@app.get("/secure-static/{file_name}")
def read_secure_static(file_name: str, user: str = Depends(authenticate)):
    return FileResponse(f"static/{file_name}")

In this case, the static file at the endpoint /secure-static/{file_name} will be served only to authenticated users.

Custom Authentication

Sometimes the built-in options may not fit your needs, and creating a custom authentication process could be beneficial. Use dependencies to implement custom logic.

For example, if you want a JSON Web Token (JWT) as a custom authentication method, you can decode the JWT and verify its claims:

from jose import JWTError, jwt
from datetime import datetime, timedelta

SECRET_KEY = "your_secret_key"
ALGORITHM = "HS256"

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

Finally, implement this token in your login route and use it for secured resources.

Testing Your API Security

No matter what type of authentication and authorization you implement, ensure thorough testing. Use tools like Postman or automated testing frameworks to validate that:

  1. Unauthorized users cannot access protected endpoints.
  2. Users with restricted roles can only access the data they are permitted.
  3. Token expiry and renewal behave as expected.

Conclusion of Practical Application

Understanding authentication and authorization are critical when developing APIs with FastAPI. By choosing the right approach, whether it’s Basic Authentication, OAuth2, or a custom JWT solution, you can effectively secure your API endpoints. Implement role-based access controls, verify user credentials, and ensure your application can flexibly respond to security demands. FastAPI provides robust tools for securing your endpoints, allowing you to focus on building features without sacrificing security.

Leave a Comment

Previous

Understanding Python’s Import System and Circular Dependencies

Next

Salary trends for Python developers: A San Francisco vs remote analysis