{"id":23159102,"url":"https://github.com/aekasitt/fastapi-csrf-protect","last_synced_at":"2025-04-12T15:35:08.273Z","repository":{"id":46138260,"uuid":"315881459","full_name":"aekasitt/fastapi-csrf-protect","owner":"aekasitt","description":"Stateless implementation of Cross-Site Request Forgery (XSRF) Protection by using Double Submit Cookie mitigation pattern","archived":false,"fork":false,"pushed_at":"2025-03-25T13:30:54.000Z","size":602,"stargazers_count":85,"open_issues_count":0,"forks_count":16,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-03T17:10:06.667Z","etag":null,"topics":["asgi","csrf","fastapi","security","xsrf"],"latest_commit_sha":null,"homepage":"https://aekasitt.github.io/fastapi-csrf-protect ","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aekasitt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-25T08:55:13.000Z","updated_at":"2025-03-25T13:30:57.000Z","dependencies_parsed_at":"2023-12-03T12:25:03.168Z","dependency_job_id":"21c3a512-8b8f-4fda-be7d-47d3f891f4e9","html_url":"https://github.com/aekasitt/fastapi-csrf-protect","commit_stats":{"total_commits":79,"total_committers":4,"mean_commits":19.75,"dds":"0.40506329113924056","last_synced_commit":"830e702ff6e7269da33350c5d0256a17a26a5b36"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aekasitt%2Ffastapi-csrf-protect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aekasitt%2Ffastapi-csrf-protect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aekasitt%2Ffastapi-csrf-protect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aekasitt%2Ffastapi-csrf-protect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aekasitt","download_url":"https://codeload.github.com/aekasitt/fastapi-csrf-protect/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248590090,"owners_count":21129747,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asgi","csrf","fastapi","security","xsrf"],"created_at":"2024-12-17T22:29:02.088Z","updated_at":"2025-04-12T15:35:08.249Z","avatar_url":"https://github.com/aekasitt.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FastAPI CSRF Protect\n\n[![Package version](https://img.shields.io/pypi/v/fastapi-csrf-protect)](https://pypi.org/project/fastapi-csrf-protect)\n[![Format](https://img.shields.io/pypi/format/fastapi-csrf-protect)](https://pypi.org/project/fastapi-csrf-protect)\n[![Python version](https://img.shields.io/pypi/pyversions/fastapi-csrf-protect)](https://pypi.org/project/fastapi-csrf-protect)\n[![License](https://img.shields.io/pypi/l/fastapi-csrf-protect)](https://pypi.org/project/fastapi-csrf-protect)\n[![Top](https://img.shields.io/github/languages/top/aekasitt/fastapi-csrf-protect)](.)\n[![Languages](https://img.shields.io/github/languages/count/aekasitt/fastapi-csrf-protect)](.)\n[![Size](https://img.shields.io/github/repo-size/aekasitt/fastapi-csrf-protect)](.)\n[![Last commit](https://img.shields.io/github/last-commit/aekasitt/fastapi-csrf-protect/master)](.)\n[![Documentation](https://img.shields.io/badge/pdoc-555?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAkUExURUdwTJHtkZDtkI/vj2rOYFXBQn3deZDukDuzAHDTaFrES4HhfmcEZqoAAAAHdFJOUwCAv0Df788Wv3t3AAACCElEQVQ4y42UsXKcMBCGuVC4Pc6FJuPGRzLDnK/xnAsKP0IeIU+QLhyFEHoAVlJlNxJHlwbBVY4LyeeXs4BLCnQzCTOAZj+0K+3/iyD4zwvhIIiiey/+iVRB8LnJPJBq6QA8eeBRuI8R8UFKTYbc7QGqQRIAOa++KKAD6LW4nQMFwgIB7gMlLaPQz8GVMlhxjD2AoKVcSeKl2jCAyq2K/5yBsiINRqSx+QwUcmhgFNmXOWivzO2CZsWTlyrl2U69qPmMjUi0pBqreY0bvi8BGGHzVaVKJnWHi2o5bwlhOI4JGF9yzeuTPua+5qoHEHvfDAvF398qPz70vboRl4DV8vESCC3HqSfsAAotkNf0sY1HhnR+AZTQruzrBXAHLLe/h9HDtIRwFa+v3XvL4bX8NXpvrLTDb31tImdezvO7dgipAYTOmhyYXAYptOvNuPVR99Ry24BieJlqEX8bdzhUWlBo3JQTMExZ//X7BNplmCgN4t3FFdecnUHJcHLi6ogfEurCujdlMwK38AMItd/FETp0TD2vi6nvW3AHYkje1VmcKJ6humyn46hB1ebkqPwhsYkJs8+jmLYp2Z5AgwkfnlRLPR7BsBTYUH3M7pEVRAMcT2dXbbWLM6d/SEFi6pKayVU75z2Oh3FKoKt7Lv/IkRw6M4mJXKrerP8aII6vz8MVxvsv//gNfQBIOvQNeKr0GQAAAABJRU5ErkJggg==)](https://aekasitt.github.io/fastapi-csrf-protect)\n\n[![Protect Banner](static/protect-banner.svg)](https://github.com/aekasitt/fastapi-csrf-protect/blob/master/static/protect-banner.svg)\n\n## Features\n\nFastAPI extension that provides stateless Cross-Site Request Forgery (XSRF) Protection support.\nAimed to be easy to use and lightweight, we adopt [Double Submit Cookie](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#double-submit-cookie) mitigation pattern.\nIf you were familiar with `flask-wtf` library this extension suitable for you.\nThis extension inspired by `fastapi-jwt-auth` 😀\n\n- Storing `fastapi-csrf-token` in cookies or serve it in template's context\n\n## Installation\n\nThe easiest way to start working with this extension with pip\n\n```bash\npip install fastapi-csrf-protect\n# or\nuv add fastapi-csrf-protect\n```\n\n## Getting Started\n\nThe following examples show you how to integrate this extension to a FastAPI App\n\n### Example Login Form\n\n```python\nfrom fastapi import FastAPI, Request, Depends\nfrom fastapi.responses import JSONResponse\nfrom fastapi.templating import Jinja2Templates\nfrom fastapi_csrf_protect import CsrfProtect\nfrom fastapi_csrf_protect.exceptions import CsrfProtectError\nfrom pydantic_settings import BaseSettings\n\napp = FastAPI()\ntemplates = Jinja2Templates(directory=\"templates\")\n\nclass CsrfSettings(BaseSettings):\n  secret_key: str = \"asecrettoeverybody\"\n  cookie_samesite: str = \"none\"\n\n@CsrfProtect.load_config\ndef get_csrf_config():\n  return CsrfSettings()\n\n@app.get(\"/login\")\ndef form(request: Request, csrf_protect: CsrfProtect = Depends()):\n  \"\"\"\n  Returns form template.\n  \"\"\"\n  csrf_token, signed_token = csrf_protect.generate_csrf_tokens()\n  response = templates.TemplateResponse(\n    \"form.html\", {\"request\": request, \"csrf_token\": csrf_token}\n  )\n  csrf_protect.set_csrf_cookie(signed_token, response)\n  return response\n\n@app.post(\"/login\", response_class=JSONResponse)\nasync def create_post(request: Request, csrf_protect: CsrfProtect = Depends()):\n  \"\"\"\n  Creates a new Post\n  \"\"\"\n  await csrf_protect.validate_csrf(request)\n  response: JSONResponse = JSONResponse(status_code=200, content={\"detail\": \"OK\"})\n  csrf_protect.unset_csrf_cookie(response)  # prevent token reuse\n  return response\n\n@app.exception_handler(CsrfProtectError)\ndef csrf_protect_exception_handler(request: Request, exc: CsrfProtectError):\n  return JSONResponse(status_code=exc.status_code, content={\"detail\": exc.message})\n\n```\n\n## Contributions\n\n### Prerequisites\n\n\n* [python](https://www.python.org) version 3.9 and above\n* [uv](https://docs.astral.sh/uv)\n\n### Setting up\n\nThe following guide walks through setting up your local working environment using `pyenv`\nas Python version manager and `uv` as Python package manager. If you do not have `pyenv`\ninstalled, run the following command.\n\n\u003cdetails\u003e\n  \u003csummary\u003e Install using Homebrew (Darwin) \u003c/summary\u003e\n  \n  ```sh\n  brew install pyenv --head\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e Install using standalone installer (Darwin and Linux) \u003c/summary\u003e\n  \n  ```sh\n  curl https://pyenv.run | bash\n  ```\n\u003c/details\u003e\n\nIf you do not have `uv` installed, run the following command.\n\n\u003cdetails\u003e\n  \u003csummary\u003e Install using Homebrew (Darwin) \u003c/summary\u003e\n\n  ```sh\n  brew install uv\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e Install using standalone installer (Darwin and Linux) \u003c/summary\u003e\n\n  ```sh\n  curl -LsSf https://astral.sh/uv/install.sh | sh\n  ```\n\u003c/details\u003e\n\nOnce you have `pyenv` Python version manager installed, you can\ninstall any version of Python above version 3.9 for this project.\nThe following commands help you set up and activate a Python virtual\nenvironment where `uv` can download project dependencies from the `PyPI`\nopen-sourced registry defined under `pyproject.toml` file.\n\n\u003cdetails\u003e\n  \u003csummary\u003e Set up environment and synchronize project dependencies \u003c/summary\u003e\n\n  ```sh\n  pyenv shell 3.11.9\n  uv venv  --python-preference system\n  source .venv/bin/activate\n  ```\n\u003c/details\u003e\n\n### Getting started\n\nTo contribute to the project, fork the repository and clone to your local device\nand install preferred testing dependency [pytest](https://github.com/pytest-dev/pytest)\nAlternatively, run the following command on your terminal to do so:\n\n```bash\nuv sync --dev\n```\n\nTesting can be done by the following command post-installation:\n\n```bash\nuv sync --dev --extras test\npytest\n```\n\n## Changelog\n\n### 🚧 Breaking Changes (0.3.0 -\u003e 0.3.1) The double submit update\n\n* The `generate_csrf` method has now been marked for deprecation\n* The recommended method is now `generate_csrf_tokens` which returns a tuple of tokens, first unsigned\n  and the latter signed\n* Recommended pattern is for the first token is aimed for returning as part of context\n* Recommended pattern is for the signed token to be set in client's cookie completing [Double Submit Cookie](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#double-submit-cookie)\n* To prevent token reuse, protected endpoint can unset the signed CSRF Token in client's cookies as\n  per example code and recommended pattern.\n\n### 🚧 Breaking Changes (0.3.1 -\u003e 0.3.2) The anti-JavaScript update\n\n* New keys are added at setup `token_location` (either `body` or `header`) and `token_key` is key\n  where form-encoded keeps the csrf token stored, cross-checked with csrf secret in cookies.\n* Asynchronous `validate_csrf` method now needs to be awaited therefore protected endpoints need to\n  be asynchronous as well.\n\n### Error in version 0.3.5 after updating to Pydantic V2\n\n* Made a blunder when updating from Pydantic V1 to Pydantic V2 and caused an error to occur when\n  setting `cookie_samesite` in settings\n* Fixed in version `0.3.6`\n\n### Version 1.0\n\n* Remove deprecated method `generate_csrf`, please use `generate_csrf_tokens`.\n* Validate `FormData` value received for given `token_key` is in fact a string, not `UploadFile`\n\n### Version 1.0.1\n\n* Fix cookie unsetting when configuring library with cookie `Secure` and / or `SameSite=None`\n* Test cookie settings covering `SameSite` options and `Secure` usage\n* Bypass `https` tests using manual `test_client.base_url = 'https://testserver'`\n\n\n### Run Examples\n\nTo run the provided examples, first you must install extra dependencies [uvicorn](https://github.com/encode/uvicorn) and [jinja2](https://github.com/pallets/jinja/)\nAlternatively, run the following command on your terminal to do so\n\n```bash\nuv sync --extras examples\n```\n\nRunning the example utilizing form submission\n\n```bash\nuvicorn examples.body:app\n```\n\nRunning the example utilizing headers via JavaScript\n\n```bash\nuvicorn examples.header:app\n```\n\n## License\n\nThis project is licensed under the terms of the MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faekasitt%2Ffastapi-csrf-protect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faekasitt%2Ffastapi-csrf-protect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faekasitt%2Ffastapi-csrf-protect/lists"}