Published on

FastAPI Security: 3 Essential Practices to Protect Your API

Securing a FastAPI application involves implementing three core layers: authentication using OAuth2 with JWT (JSON Web Tokens), rate limiting to prevent brute-force attacks, and environment variable management to hide sensitive keys. By following these industry standards, you can protect a basic API from 90% of common web vulnerabilities in less than 30 minutes.

What do you need before starting?

To follow this guide, you should have a basic understanding of Python and how to run a simple script. Ensure you have the following installed on your machine:

  • Python 3.12 or higher: This version includes important security patches and performance improvements.
  • Pip: The package installer for Python.
  • A Code Editor: Such as VS Code, PyCharm, or Cursor.
  • FastAPI and Uvicorn: The framework and the server that runs it.

You can install the necessary libraries by running this command in your terminal:

pip install fastapi uvicorn "python-multipart" "PyJWT[crypto]" "passlib[bcrypt]" slowapi

Why is security a priority for your API?

When you build an API (Application Programming Interface - a way for programs to talk to each other), you are opening a door to your data. If that door isn't locked, anyone can delete your database or steal user information.

Security isn't just about stopping hackers; it's about ensuring your app stays online and performs well for real users. We've found that implementing security early saves hundreds of hours of debugging and "firefighting" later when your app grows.

How do you hide your secrets using environment variables?

The first rule of API security is to never hardcode secrets like database passwords or API keys directly in your code. If you upload your code to a site like GitHub, anyone can see those secrets.

Instead, use a .env file (a simple text file that stores configuration) to keep these values private. Create a file named .env in your project folder:

SECRET_KEY=your-super-secret-random-string-here
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30

In your Python code, you can use the python-dotenv library or FastAPI's built-in Pydantic settings to read these values. This keeps your credentials safe and makes it easy to change them without touching the code.

How do you handle user passwords safely?

You should never store a user's password as plain text in your database. If a hacker gets access to your data, they would see every user's password immediately.

Instead, you use a process called "hashing" (turning a password into a long, scrambled string of characters that cannot be reversed). We recommend using the passlib library with the bcrypt algorithm.

Here is how you can set up a password hashing utility:

from passlib.context import CryptContext

# Define the hashing algorithm
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def get_password_hash(password):
    # This turns "my-password" into something like "$2b$12$..."
    return pwd_context.hash(password)

def verify_password(plain_password, hashed_password):
    # This checks if the entered password matches the stored hash
    return pwd_context.verify(plain_password, hashed_password)

What is JWT and how do you use it for authentication?

JWT (JSON Web Token) is a standard way to securely transmit information between a client and a server. Think of it like a digital ID card that the server gives to a user after they log in.

The user sends this "ID card" with every request, so the server knows who they are. To do this safely in 2026, you should use the PyJWT library.

Step 1: Create a function to generate a token.

import jwt
from datetime import datetime, timedelta, timezone

def create_access_token(data: dict, expires_delta: timedelta | None = None):
    to_encode = data.copy()
    # Set the expiration time for the token
    expire = datetime.now(timezone.utc) + (expires_delta or timedelta(minutes=15))
    to_encode.update({"exp": expire})
    
    # Sign the token with your SECRET_KEY
    encoded_jwt = jwt.encode(to_encode, "YOUR_SECRET_KEY", algorithm="HS256")
    return encoded_jwt

Step 2: Add this to your login route. When a user provides the correct username and password, you send them this token back.

How do you stop bots with rate limiting?

Rate limiting is a technique used to limit how many times a user can call your API in a specific timeframe. This prevents "brute-force attacks" (where a bot tries thousands of passwords a second) and "DDoS attacks" (where someone tries to crash your server by overloading it).

For FastAPI, the slowapi library is the standard choice. It works seamlessly with the latest FastAPI middleware (software that processes requests before they reach your logic).

from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded

# Set up the limiter to track users by their IP address
limiter = Limiter(key_func=get_remote_address)
app = FastAPI()
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

@app.get("/secure-data")
@limiter.limit("5/minute") # Allow only 5 requests per minute
async def secure_data():
    return {"message": "This is protected and rate-limited!"}

What you should see: If you refresh your browser more than five times in a minute, you will receive a "429 Too Many Requests" error. Don't worry if this happens during testing; it means the security is working.

What are common security mistakes beginners make?

Even with the best tools, small mistakes can lead to big problems. Here are three common "gotchas" to avoid:

  1. Using a weak Secret Key: Your SECRET_KEY should be a long, random string. If it's easy to guess, hackers can create their own fake "ID cards" (JWTs).
  2. Forgetting HTTPS: Even if your API is secure, if you don't use HTTPS (Hypertext Transfer Protocol Secure), someone on the same Wi-Fi could "sniff" the data as it travels through the air. In 2026, always use a provider that offers an SSL certificate.
  3. Exposing Tracebacks: When your code crashes, FastAPI might show a "traceback" (a detailed report of the error). If this is visible to the public, it might reveal your folder structure or database names. Always set debug=False when you put your app online.

Next Steps

Now that you have the basics down, you can try adding more advanced features. You might explore "Role-Based Access Control" (RBAC), which allows you to give different permissions to different users, such as "Admin" or "Editor."

It is normal to feel overwhelmed by security at first. Start by hiding your secrets and hashing passwords, then move on to tokens and rate limiting as you get more comfortable.

For more detailed guides, visit the official FastAPI documentation.


Read the Your Documentation