How to secure APIs built with FastAPI: A complete guide
Want to know how to secure your APIs built with FastAPI? Dive into our latest blog post, where we guide you through the best practices for FastAPI security.
Want to know how to protect your APIs built with the FastAPI web framework? Dive into our latest blog post, where we guide you through the best practices for FastAPI security. Explore how these techniques can not only enhance the security of your web applications but also bring tangible benefits to your development journey.
In this guide, Escape's security research team has gathered the most crucial tips to protect your FastAPI applications from potential data breaches. Our goal is to empower you to create more resilient and efficient FastAPI projects. Let's get started!
What are the key features of the FastAPI framework?
FastAPI is a modern Python web framework with several key features (if you're not a beginner, jump to the next section for a technical write-up):
- Fast: As the name suggests, FastAPI is designed the for high performance. It leverages the asynchronous capabilities of Python to handle concurrent requests efficiently, making it ideal for building APIs that need to scale.
- Easy to use: FastAPI is designed to be intuitive and easy to use. Its syntax is clean and concise, allowing developers to quickly build robust APIs with minimal boilerplate code.
- Automatic documentation: One standout feature of FastAPI is its automatic API documentation generation (for example, OpenAPI and JSON Schema). By leveraging Python-type hints, FastAPI can automatically generate detailed API documentation, including request and response models, parameter descriptions, and example usage.
- Seamless integration with popular databases: FastAPI integrates with popular databases like SQLAlchemy and ORMs, allowing developers to easily interact with the database without writing complex SQL queries. Using SQLAlchemy also helps to prevent SQL injection attacks when interacting with databases.
You can watch this YouTube video from Jose Haro Peralta to learn how to use SQLAlchemy in a FastAPI application. - Type checking: FastAPI makes extensive use of Python type hints for both request and response validation. This not only helps catch errors early in the development process but also improves code readability and maintainability.
- Built-in support for WebSockets: In addition to traditional HTTP endpoints, FastAPI provides built-in support for WebSockets, making it easy to build real-time applications that require bidirectional communication between clients and servers.
- Integration with Pydantic: FastAPI seamlessly integrates with Pydantic, a data validation library for Python. This allows developers to easily define and validate complex data models for their API endpoints.
- Extensible: FastAPI is highly extensible, with support for middleware, dependency injection, and custom validation logic. This allows developers to tailor the framework to their specific needs and integrate with third-party libraries seamlessly.
If you're still doubting about all the advantages of FastAPI, check out this video:
How to get started building APIs with FastAPI
Setting up FastAPI
To get started with FastAPI, you'll first need to install it. Luckily, installing FastAPI is a breeze. All you need is Python 3.7 (or above) and pip, the Python package installer. Simply open up your terminal or command prompt and run the command pip install fastapi
. Once the installation is complete, you're all set to start using FastAPI. It's that easy!
How to build an API with FastAPI
FastAPI makes it easy to build APIs with its intuitive and powerful features. You can easily create routes by defining functions and using the @app.route()
decorator.
To this end, define a route with automatic request and response validation using Python type hints:
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str = None
@app.post("/items/")
async def create_item(item: Item):
return item # FastAPI automatically validates and serializes the response
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
Each route can have different methods such as GET, POST, PUT, DELETE, etc., allowing you to handle different types of requests.
FastAPI also provides automatic request and response validation, making it easy to ensure that the data sent and received is of the correct type. For example, you can use Python type hints to specify the expected input and output types for each route. This not only helps in maintaining the documentation but also saves time by automatically generating serialization and deserialization code.
With FastAPI, you can easily handle query parameters, request bodies, path parameters, and more by simply defining function parameters. This makes it very convenient to access and process the data sent by the client. Overall, FastAPI simplifies the process of building APIs and allows you to focus on writing the core logic of your application.
Request handling and validation
In FastAPI, handling and validating requests is made easy and efficient. With just a few lines of code, you can define the expected structure and types of data in each request.
FastAPI uses the Pydantic library we mentioned before, which allows you to create Python classes with attributes and types that correspond to the expected JSON bodies of your requests. This way, you can automatically validate the incoming data and ensure that it matches the expected format.
FastAPI also provides convenient decorators like @app.post()
and @app.get()
to handle different types of HTTP requests. You can easily access the request parameters, headers, and cookies through the Request
object. This gives you the flexibility to handle and validate the requests according to your specific needs.
To illustrate this, let's create a FastAPI application that defines and validates request data using Pydantic models:
from fastapi import FastAPI, Request
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str = None
@app.post("/create_item/")
async def create_item(item: Item):
return {"item": item}
@app.get("/read_item/{item_id}")
async def read_item(item_id: int, request: Request):
headers = request.headers
cookies = request.cookies
return {"item_id": item_id, "headers": headers, "cookies": cookies}
Database integration with FastAPI
FastAPI simplifies database integration. Install the database driver, import it, and establish a connection. Dependency Injection ensures a single connection instance for efficient database interactions and CRUD operations. Use ORMs like SQLAlchemy or Tortoise-ORM to define models, query, and manipulate data.
Best practices for securing Fastapi
Selection of vulnerable FastAPI applications
Are you a practical learner? Don't hesitate to dive into our selection of vulnerable FastAPI applications to discover their vulnerabilities, exploit and try to remediate them:
- Vulnerable FastAPI integrating OWASP TOP 10 (2021). Vulnerable FastAPI is a simple vulnerable FastAPI application for learning API pentesting on vulnerable API endpoints.
- FastAPI app with Jinja2 SSTI vulnerability example to demonstrate security risks in web applications.
- Vulnerable FastAPI app with a bonus exploit - SQL Injection
- Vulnerable REST API made with FastAPI for security testing purposes
First step: Use HTTPS for secure communication
To ensure secure communication with your FastAPI application, it is highly recommended to use HTTPS.
HTTPS adds an extra layer of security by encrypting data transmission between the client and the server. By using HTTPS, you can protect sensitive information like passwords, credit card details, and other personal data from being intercepted or tampered with. Implementing HTTPS in FastAPI is straightforward.
You can use a digital certificate to enable secure communication, and the --cert
and --key
options in uvicorn allow you to specify the SSL certificate and key files.
Here's an example of how to enable HTTPS with FastAPI:
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=8000, ssl_keyfile="path/to/key.pem", ssl_certfile="path/to/cert.pem")
By following this best practice and using HTTPS, you can enhance the security of your FastAPI application and protect your users' sensitive data.
Validate and sanitize user input
FastAPI provides built-in support for validating and sanitizing user input, which is crucial for ensuring the security of your application.
By validating and sanitizing user input, you can prevent potential security vulnerabilities such as SQL injection, cross-site scripting (XSS) attacks and CSRF (Cross-Site Request Forgery). We'll dive into how to use advanced external libraries to protect against the last two vulnerabilities further in the article.
FastAPI allows you to define models for your input data using Pydantic
, which automatically validates and sanitizes the incoming data based on the specified rules. For example, you can define a model that specifies the expected data types and constraints for each input field:
from fastapi import FastAPI, Query
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
@app.post("/items/")
async def create_item(item: Item):
# Here, item is automatically validated against the Item model
# If validation fails, FastAPI will automatically return an error response
# with details about the validation errors.
# Once validated, you can safely use the data in your application logic
item_dict = item.dict()
price_with_tax = item.price + (item.tax or 0)
item_dict.update({"price_with_tax": price_with_tax})
# Here you can use the validated and sanitized data as needed
return item_dict
- We define a Pydantic model
Item
that represents the structure of the data we expect to receive in the request body. - FastAPI automatically validates incoming requests against this model. If the request data doesn't match the model's schema, FastAPI will return an error response.
- The
create_item
endpoint expects a POST request with JSON data representing anItem
. - Once the data is validated, we can safely use it in our application logic.
- We calculate the
price_with_tax
and return a response containing the processed data.
Implement rate limiting
Implementing rate limiting is an essential practice to enhance the security of your FastAPI application.
These techniques help prevent abuse and protect your server from being overwhelmed by excessive requests. By setting limits on the number of requests a client can make within a certain time frame, you can prevent malicious actors from launching denial-of-service attacks or scraping sensitive data.
FastAPI provides built-in support for rate limiting and throttling through external libraries like fastapi-limiter
or fastapi-utils
. With just a few lines of code, you can configure rate limits based on IP address, user, or any other criteria you choose.
You can install fastapi-limiter
via pip: pip install fastapi-limiter
from fastapi import FastAPI
from fastapi_limiter import FastAPILimiter
from fastapi_limiter.depends import RateLimiter
app = FastAPI()
# Initialize FastAPILimiter
limiter = FastAPILimiter(app)
@limiter.limit("5/minute")
@app.get("/items/")
async def read_items():
return {"message": "This endpoint is rate-limited."}
fastapi-limiter
provides various options for configuring rate limiting, such as using different storage backends (e.g., in-memory, Redis) and customizing rate limit headers and error messages. You can refer to the library's documentation GitHub for more details on advanced usage and configuration options.
Implementing authentication & authorization in FastAPI
Implementing JWT authentification
The most secure authentication mechanism often involves using JWT (JSON Web Tokens) with appropriate security measures. Here's how you can implement JWT-based authentication with FastAPI, incorporating best API security practices:
You can install pyjwt
with pip
: pip install pyjwt
Then, define a user model to represent users in your application. This model should include fields such as username, password (hashed), and any other relevant information.
from pydantic import BaseModel
class User(BaseModel):
username: str
password: str
Implement an authentication service responsible for authenticating users and generating JWT tokens.
from fastapi import HTTPException, Depends
from fastapi.security import OAuth2PasswordBearer
import jwt
from passlib.context import CryptContext
# Secret key for signing JWT tokens. We'll provide example including secret key rotation below.
SECRET_KEY = "hello-from-escape-team"
# Algorithm used for JWT token encoding
ALGORITHM = "HS256"
# Password hashing context
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# OAuth2 password bearer flow for token retrieval
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
# Mock database of users (replace with your user database logic)
fake_users_db = {
"user1": {
"username": "user1",
"password": "$2b$12$AQyHPwd7p1s.GQvax/A3ve5wMey6NZuDXW1/FVhDpi8s/MV/Fo1LC", # hashed password: 'password1'
"disabled": False,
}
}
# Authentication function
def authenticate_user(username: str, password: str):
user = fake_users_db.get(username)
if not user or not pwd_context.verify(password, user["password"]):
return False
return user
# Token generation function
def create_access_token(data: dict):
encoded_jwt = jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
# Dependency for extracting and verifying JWT token
def get_current_user(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise HTTPException(status_code=401, detail="Invalid authentication credentials")
token_data = {"username": username}
except jwt.JWTError:
raise HTTPException(status_code=401, detail="Invalid authentication credentials")
return token_data
Implement an endpoint for generating JWT tokens upon successful authentication:
from fastapi import FastAPI, Depends
from fastapi.security import OAuth2PasswordRequestForm
app = FastAPI()
@app.post("/token")
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(status_code=401, detail="Incorrect username or password")
token_data = {"sub": user["username"]}
access_token = create_access_token(token_data)
return {"access_token": access_token, "token_type": "bearer"}
Implement a protected endpoint that requires authentication using JWT tokens:
@app.get("/protected")
async def protected_route(current_user: dict = Depends(get_current_user)):
return {"message": f"Beware, {current_user['username']}. This is a protected route."}
Below is the final code, including secret key rotation:
from fastapi import FastAPI, HTTPException, Depends
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel
from passlib.context import CryptContext
import jwt
import threading
import time
app = FastAPI()
# Secret key for signing JWT tokens
SECRET_KEY = os.environ.get("SECRET_KEY", None)
# If SECRET_KEY is not provided as an environment variable, generate a random one
if SECRET_KEY is None:
SECRET_KEY = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(64))
# Algorithm used for JWT token encoding
ALGORITHM = "HS256"
# Password hashing context
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# OAuth2 password bearer flow for token retrieval
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
# Mock database of users (replace with your user database logic)
fake_users_db = {
"user1": {
"username": "user1",
"password": "$2b$12$AQyHPwd7p1s.GQvax/A3ve5wMey6NZuDXW1/FVhDpi8s/MV/Fo1LC", # hashed password: 'password1'
"disabled": False,
}
}
# Define User model
class User(BaseModel):
username: str
password: str
# Authentication function
def authenticate_user(username: str, password: str):
user = fake_users_db.get(username)
if not user or not pwd_context.verify(password, user["password"]):
return False
return user
# Token generation function
def create_access_token(data: dict):
encoded_jwt = jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
# Dependency for extracting and verifying JWT token
def get_current_user(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise HTTPException(status_code=401, detail="Invalid authentication credentials")
token_data = {"username": username}
except jwt.JWTError:
raise HTTPException(status_code=401, detail="Invalid authentication credentials")
return token_data
# Secret key rotation functionality
def rotate_secret_key():
"""Rotate the secret key."""
global SECRET_KEY
new_secret_key = generate_secret_key()
SECRET_KEY = new_secret_key
print("Secret key rotated.")
def schedule_key_rotation(interval_seconds):
"""Schedule secret key rotation at regular intervals."""
while True:
rotate_secret_key()
time.sleep(interval_seconds)
def generate_secret_key(length=32):
"""Generate a random string of letters and digits for the secret key."""
chars = string.ascii_letters + string.digits
return ''.join(random.choice(chars) for _ in range(length))
if __name__ == "__main__":
# Start key rotation in a separate thread
rotation_interval_seconds = 3600 # Rotate key every hour (adjust as needed)
rotation_thread = threading.Thread(target=schedule_key_rotation, args=(rotation_interval_seconds,))
rotation_thread.daemon = True
rotation_thread.start()
# Run FastAPI app
# Implement the token endpoint for token generation
@app.post("/token")
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(status_code=401, detail="Incorrect username or password")
token_data = {"sub": user["username"]}
access_token = create_access_token(token_data)
return {"access_token": access_token, "token_type": "bearer"}
# Implement a protected endpoint that requires authentication using JWT tokens
@app.get("/protected")
async def protected_route(current_user: dict = Depends(get_current_user)):
return {"message": f"Beware, {current_user['username']}. This is a protected route."}
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Implementing Role-Based authorization in FastAPI
Role-based authorization allows you to control access to certain resources in your FastAPI application based on the roles or permissions of the authenticated user.
This is useful when you have different user roles with varying levels of access. In FastAPI, you can implement role-based authorization by using decorators or middleware. One way to do this is by creating a decorator function that checks if the authenticated user has the required role before allowing access to a specific route or endpoint.
Here's an example of how you can implement role-based authorization using decorators:
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel
from typing import List
app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def check_roles(roles: List[str]):
def decorator(func):
def wrapper(*args, **kwargs):
# Get the current user's roles from the database or token
# Check if any of the roles match the required roles
# If not, raise an HTTPException with 403 status code
# Else, continue with the execution of the function
return func(*args, **kwargs)
return wrapper
return decorator
@app.get("/protected_route")
@check_roles(["admin"])
def protected_route():
return {"message": "You have access to this protected route!"}
In this example, the check_roles
decorator takes a list of required roles as an argument. Inside the decorator, you would typically retrieve the authenticated user's roles from the database or token and compare them with the required roles. If any of the roles match, the decorator allows access to the route or endpoint. Otherwise, it raises an HTTPException
with a 403 status code, indicating that the user does not have the required roles.
By using this approach, you can easily implement role-based authorization in your FastAPI application and control access to your resources based on user roles.
Protection against common vulnerabilities (maintained libraries included)
How to secure FastAPI APIs against XSS
Another common vulnerability is Cross-Site Scripting (XSS), which can be mitigated by escaping user-generated content before rendering it in HTML templates.
You can integrate third-party libraries or implement custom middleware to add XSS protection.
bleach
library. Bleach heavily relies on html5lib which is no longer in active development. It was deprecated on Jan 23, 2023nh3
is almost the exact same API as bleach
from an end-user perspective, but it's way faster and actively maintained.
Below is an example of how you can use the nh3
library to sanitize user input and prevent XSS attacks:
First, install the nh3
library using pip:
pip install nh3
Then, you can use nh3
to sanitize user input in your FastAPI application. Use clean()
to sanitize HTML fragments:
>>> import nh3
>>> nh3.clean("<unknown>hi")
'hi'
>>> nh3.clean("<b><img src='' onerror='alert(\\'hax\\')'>XSS?</b>")
'<b><img src="">XSS?</b>'
For more information on customization, check out nh3
docs.
How to secure FastAPI API against CSRF
To secure a FastAPI API against Cross-Site Request Forgery (CSRF) attacks, you can use an extension FastAPI CSRF Protect.
While there are other ways to get CSRF protection in FastAPI (like itsdangerous
library, which can be used to generate and verify CSRF tokens or using Piccolo-API's middleware), FastAPI CSRF Protect is one of the safest and the most flexible ways to get CSRF protection.
To get started:
pip install fastapi-csrf-protect
Then, you can implement CSRF protection in your FastAPI application as follows:
from fastapi import FastAPI
from fastapi_csrf_protect import CsrfProtect
app = FastAPI()
# Initialize CsrfProtect with a secret key
csrf = CsrfProtect(app, app.secret_key)
@app.get("/")
async def read_root():
return {"message": "Hello from Escape"}
@app.post("/secure")
async def secure_endpoint():
return {"message": "This endpoint is CSRF protected"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Always remember to avoid hard-coding secret key in your code. Solutions like AWS Secrets Manager, or HashiCorp Vault are great for supplying secrets during run time. Here's an example of how you can implement secret key rotation in a FastAPI application using Python's os module to interact with environment variables:
import os
import random
import string
import time
from fastapi import FastAPI
app = FastAPI()
def generate_secret_key(length=32):
"""Generate a random string of letters and digits for the secret key."""
chars = string.ascii_letters + string.digits
return ''.join(random.choice(chars) for _ in range(length))
def rotate_secret_key():
"""Rotate the secret key."""
new_secret_key = generate_secret_key()
os.environ["SECRET_KEY"] = new_secret_key
def schedule_key_rotation(interval_seconds):
"""Schedule secret key rotation at regular intervals."""
while True:
rotate_secret_key()
print("Secret key rotated.")
time.sleep(interval_seconds)
@app.get("/")
async def read_root():
return {"message": "Hello from Escape"}
if __name__ == "__main__":
# Start key rotation in a separate thread or process
rotation_interval_seconds = 3600 # Rotate key every hour (adjust as needed)
import threading
rotation_thread = threading.Thread(target=schedule_key_rotation, args=(rotation_interval_seconds,))
rotation_thread.daemon = True
rotation_thread.start()
Creating a /csrftoken/
endpoint in your FastAPI application can be beneficial, especially if you need to obtain CSRF tokens for client-side operations such as AJAX requests or SPA (Single Page Application) interactions. This endpoint would generate and return a CSRF token upon request.
Here's how you can implement such an endpoint:
from fastapi import FastAPI
from fastapi_csrf_protect import CsrfProtect
app = FastAPI()
csrf = CsrfProtect(app)
@app.get("/csrftoken/")
def get_csrf_token(csrf_protect: CsrfProtect = Depends()):
"""Endpoint to obtain a CSRF token."""
csrf_token, _ = csrf_protect.generate_csrf_tokens()
return {"csrf_token": csrf_token}
Here is an example that combines all the details listed above of how to integrate this extension for the login form of FastAPI API where you want to protect the /login/
POST handler.
You can later on modify the URL path for the endpoint.
import os
import random
import string
import threading
import time
from fastapi import FastAPI, Request, Depends
from fastapi.responses import JSONResponse
from fastapi.templating import Jinja2Templates
from fastapi_csrf_protect import CsrfProtect
from fastapi_csrf_protect.exceptions import CsrfProtectError
from pydantic import BaseModel
app = FastAPI()
templates = Jinja2Templates(directory="templates")
class CsrfSettings(BaseModel):
secret_key: str = os.environ.get("SECRET_KEY", "staysecureyourescapeteam")
cookie_samesite: str = "none"
@CsrfProtect.load_config
def get_csrf_config():
return CsrfSettings()
def generate_secret_key(length=32):
"""Generate a random string of letters and digits for the secret key."""
chars = string.ascii_letters + string.digits
return ''.join(random.choice(chars) for _ in range(length))
def rotate_secret_key():
"""Rotate the secret key."""
new_secret_key = generate_secret_key()
os.environ["SECRET_KEY"] = new_secret_key
print("Secret key rotated.")
def schedule_key_rotation(interval_seconds):
"""Schedule secret key rotation at regular intervals."""
while True:
rotate_secret_key()
time.sleep(interval_seconds)
@app.get("/csrftoken/")
def get_csrf_token(csrf_protect: CsrfProtect = Depends()):
"""Endpoint to obtain a CSRF token."""
csrf_token, _ = csrf_protect.generate_csrf_tokens()
return {"csrf_token": csrf_token}
@app.get("/login")
def form(request: Request, csrf_protect: CsrfProtect = Depends()):
"""
Returns form template.
"""
csrf_token, signed_token = csrf_protect.generate_csrf_tokens()
response = templates.TemplateResponse(
"form.html", {"request": request, "csrf_token": csrf_token}
)
csrf_protect.set_csrf_cookie(signed_token, response)
return response
@app.post("/login", response_class=JSONResponse)
async def create_post(request: Request, csrf_protect: CsrfProtect = Depends()):
"""
Creates a new Post
"""
await csrf_protect.validate_csrf(request)
response: JSONResponse = JSONResponse(status_code=200, content={"detail": "OK"})
csrf_protect.unset_csrf_cookie(response) # prevent token reuse
return response
"""
Handles any validation errors that show up
"""
@app.exception_handler(CsrfProtectError)
def csrf_protect_exception_handler(request: Request, exc: CsrfProtectError):
return JSONResponse(status_code=exc.status_code, content={"detail": exc.message})
if __name__ == "__main__":
# Start key rotation in a separate thread
rotation_interval_seconds = 3600 # Rotate key every hour (adjust as needed)
rotation_thread = threading.Thread(target=schedule_key_rotation, args=(rotation_interval_seconds,))
rotation_thread.daemon = True
rotation_thread.start()
# Run FastAPI app
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
The SECRET_KEY
is retrieved from the environment variables using os.environ.get()
. If it's not found, a default value ("staysecureyourescapeteam"
) is used.
This setup helps protect your FastAPI API against CSRF attacks.
Conclusion
In conclusion, securing APIs built with FastAPI is a multifaceted task requiring a comprehensive approach to mitigate potential risks and ensure the confidentiality, integrity, and availability of data. By implementing robust authentication and authorization mechanisms, validating and sanitizing user input, and rate limiting, developers can establish a solid foundation for API protection. Leveraging FastAPI libraries such as fastapi-csrf-protect
, fastapi-limiter
or nh3
streamlines the integration of these security measures into FastAPI APIs.
Regular security audits, automated API security testing using API security tools like Escape which supports frameworks like FastAPI and staying informed about emerging security practices within the FastAPI are crucial in keeping your APIs secure.
Did you know that Escape can scan all your exposed API endpoints within minutes and help you remediate any issues. The best part is that we do all this without any traffic monitoring. Want to see Escape in action?