MCPcopy Index your code
hub / github.com/aekasitt/fastapi-csrf-protect

github.com/aekasitt/fastapi-csrf-protect @v0.3.3

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.3.3 ↗ · + Follow
63 symbols 241 edges 16 files 14 documented · 22%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

FastAPI CSRF Protect

Build Status Package Vesion Format Python Version License

Features

FastAPI extension that provides stateless Cross-Site Request Forgery (XSRF) Protection support. Aimed to be easy to use and lightweight, we adopt Double Submit Cookie mitigation pattern. If you were familiar with flask-wtf library this extension suitable for you. This extension inspired by fastapi-jwt-auth 😀

  • Storing fastapi-csrf-token in cookies or serve it in template's context

Installation

The easiest way to start working with this extension with pip

pip install fastapi-csrf-protect
# or
poetry add fastapi-csrf-protect

Getting Started

The following examples show you how to integrate this extension to a FastAPI App

Example Login Form

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 = "asecrettoeverybody"
  cookie_samesite: str = "none"

@CsrfProtect.load_config
def get_csrf_config():
  return CsrfSettings()

@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

@app.exception_handler(CsrfProtectError)
def csrf_protect_exception_handler(request: Request, exc: CsrfProtectError):
  return JSONResponse(status_code=exc.status_code, content={"detail": exc.message})

Contributions

To contribute to the project, fork the repository and clone to your local device and install preferred testing dependency pytest Alternatively, run the following command on your terminal to do so:

pip install -U poetry
poetry install

Testing can be done by the following command post-installation:

poetry install --with test
pytest

Changelog

🚧 Breaking Changes (0.3.0 -> 0.3.1) The double submit update

  • The generate_csrf method has now been marked for deprecation
  • The recommended method is now generate_csrf_tokens which returns a tuple of tokens, first unsigned and the latter signed
  • Recommended pattern is for the first token is aimed for returning as part of context
  • Recommended pattern is for the signed token to be set in client's cookie completing Double Submit Cookie
  • To prevent token reuse, protected endpoint can unset the signed CSRF Token in client's cookies as per example code and recommended pattern.

🚧 Breaking Changes (0.3.1 -> 0.3.2) The anti-JavaScript update

  • New keys are added at setup token_location (either body or header) and token_key is key where form-encoded keeps the csrf token stored, cross-checked with csrf secret in cookies.
  • Asynchronous validate_csrf method now needs to be awaited therefore protected endpoints need to be asynchronous as well.

Run Examples

To run the provided examples, first you must install extra dependencies uvicorn and jinja2 Alternatively, run the following command on your terminal to do so

poetry install --with examples

Running the example utilizing form submission

uvicorn examples.body:app

Running the example utilizing headers via JavaScript

uvicorn examples.header:app

License

This project is licensed under the terms of the MIT license.

Core symbols most depended-on inside this repo

generate_csrf_tokens
called by 5
fastapi_csrf_protect/core.py
set_csrf_cookie
called by 4
fastapi_csrf_protect/core.py
unset_csrf_cookie
called by 4
fastapi_csrf_protect/core.py
validate_csrf
called by 4
fastapi_csrf_protect/core.py
get_csrf_from_body
called by 1
fastapi_csrf_protect/core.py
get_csrf_from_headers
called by 1
fastapi_csrf_protect/core.py
generate_csrf
called by 0
fastapi_csrf_protect/core.py
validate_csrf_methods
called by 0
fastapi_csrf_protect/load_config.py

Shape

Function 29
Method 16
Class 10
Route 8

Languages

Python100%

Modules by API surface

fastapi_csrf_protect/exceptions.py8 symbols
fastapi_csrf_protect/core.py8 symbols
examples/header.py7 symbols
examples/form_data.py7 symbols
examples/body.py7 symbols
tests/__init__.py6 symbols
fastapi_csrf_protect/load_config.py5 symbols
tests/missing_token.py3 symbols
tests/token_reuse.py2 symbols
tests/token_invalid.py2 symbols
tests/token_expired.py2 symbols
tests/missing_secret.py2 symbols

For agents

$ claude mcp add fastapi-csrf-protect \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page