Skip to main content

Working with CSRF and Sessions

FastAPI Middleware, CORS, CSRF, and Sessions

Working with CSRF and Sessions

FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. In this tutorial, we'll learn about CSRF (Cross-Site Request Forgery) and how to work with sessions in FastAPI.

Understanding CSRF

Cross-Site Request Forgery (CSRF) is an attack that tricks the victim into submitting a malicious request. It uses the identity and privileges of the victim to perform an undesired function on their behalf.

For most sites, browser requests automatically include any credentials associated with the site, such as the user's session cookie, IP address, etc. Therefore, if the user is authenticated to the site, the site cannot distinguish between legitimate requests and forged requests.

Mitigating CSRF Attacks

To mitigate CSRF attacks, we need a CSRF token. The server will generate a unique token for every session when it exposes any endpoint that could potentially be vulnerable to CSRF attacks. This token is then returned to the client and the client must submit it with every subsequent request.

To implement this in FastAPI, we can use the csrf_protect package. Here's how you can do it:

from fastapi import FastAPI, Depends
from fastapi_csrf_protect import CsrfProtect
from fastapi_csrf_protect.exceptions import CsrfProtectError

app = FastAPI()

@app.exception_handler(CsrfProtectError)
async def csrf_protect_exception_handler(request, exc):
return PlainTextResponse(str(exc.detail), status_code=exc.status_code)

@app.post('/login')
async def login(data: AuthModel, csrf_protect: CsrfProtect = Depends()):
token = await csrf_protect.generate_csrf_token()
response = JSONResponse(content={'detail': 'Login Successful'})
response.set_cookie('CSRF-Token', token, httponly=True)
return response

In the code above, we first import necessary modules and create an instance of our FastAPI app. We then set up an exception handler for any CsrfProtectError that might occur. In our login route, we generate a CSRF token after the user has been authenticated and set it as a cookie in the response.

Understanding Sessions

In web development, a session is a server-side storage of information that is desired to persist throughout the user's interaction with the web site or web application. Instead of storing large and frequently changing information via cookies in the user's browser, only a unique identifier is stored on the client side (session id).

Working with Sessions in FastAPI

FastAPI doesn't come with built-in session handling. However, we can use the Starlette's sessions that works perfectly with FastAPI.

from fastapi import FastAPI, Request
from starlette.middleware.sessions import SessionMiddleware

app = FastAPI()

app.add_middleware(SessionMiddleware, secret_key='your-secret-key')

@app.get("/items/")
async def read_items(request: Request):
if "username" in request.session:
username = request.session["username"]
return {"username": username}
else:
request.session["username"] = "anonymous"
return {"username": "anonymous"}

In the code above, we first add SessionMiddleware to our app, providing a secret key for encryption. Then, in our route, we check if a username is in our session. If it is, we return it; if it is not, we add it and then return it.

Remember, sessions should be used sparingly as they can add load to your server. Also, never store sensitive data in sessions as they can be prone to session hijacking or session sidejacking attacks.

That's all for this tutorial! You've learned about CSRF and how to mitigate it in FastAPI, as well as how to use sessions in FastAPI. Happy coding!