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!