# fastapi-csrf-jinja
`fastapi-csrf-jinja` is a CSRF middleware for FastAPI applications that supports tokens in both headers and HTML forms. This library is based on `starlette-csrf`, with additional support for Jinja template integration.
## How it works?
1. The user makes a first request with a method considered safe (by default `GET`, `HEAD`, `OPTIONS`, `TRACE`).
2. It receives in response a cookie (named by default `csrftoken`) which contains a secret value.
3. When the user wants to make an unsafe request, the server expects them to send the same secret value in a header (named by default `x-csrftoken`). Additionally, the middleware now allows submission of the token via HTML forms using Jinja.
4. The middleware compares the secret value provided in the cookie with the value in the header or form:
* If they match, the request is processed.
* Otherwise, a `403 Forbidden` error response is given.
## Features
- Supports CSRF tokens in headers and HTML forms.
- Jinja template processor for easy CSRF token management in forms.
## Installation
```bash
pip install fastapi-csrf-jinja
```
## Usage with FastAPI
```py
from fastapi import FastAPI
from fastapi.templating import Jinja2Templates
from fastapi_csrf_jinja.middleware import FastAPICSRFJinjaMiddleware
from fastapi_csrf_jinja.jinja_processor import csrf_token_processor
app = FastAPI()
cookie_name = "your_cookie_name"
header_name = "your_header_name"
app.add_middleware(
FastAPICSRFJinjaMiddleware,
secret = "your_secret",
cookie_name = cookie_name,
header_name = header_name,
)
templates = Jinja2Templates(
directory="templates",
context_processors=[csrf_token_processor(cookie_name, header_name)]
)
```
- Defaults to `cookie_name` as `"csrftoken"` and `header_name` as `"x-csrftoken"` if not specified.
## Usage with Jinja and HTML forms
Now, the middleware integrates with a context processor, a function that returns a dictionary containing the CSRF token, CSRF input, and CSRF header for use with other tools such as HTMX.
Simply using {{ csrf_input | safe }} in each form is now sufficient to ensure a more secure web application. For example:
```html
<form method="post">
{{ csrf_input | safe }}
<!-- Other form fields here -->
<button type="submit">Submit</button>
</form>
```
Furthermore, we can use {{ csrf_header }} in HTMX requests. For example:
```html
<form hx-patch="/route/edit" hx-headers='{{ csrf_header | tojson | safe }}' hx-trigger="submit" hx-target="#yourtarget" hx-swap="outerHTML" >
<!-- Other form fields here -->
<button type="submit">Submit</button>
</form>
```
## Arguments
* `secret` (`str`): Secret to sign the CSRF token value. **Be sure to choose a strong passphrase and keep it SECRET**.
* `required_urls` (`Optional[List[re.Pattern]]` - `None`): List of URL regexes that the CSRF check should **always** be enforced, no matter the method or the cookies present.
* `exempt_urls` (`Optional[List[re.Pattern]]` - `None`): List of URL regexes that the CSRF check should be skipped on. Useful if you have any APIs that you know do not need CSRF protection.
* `sensitive_cookies` (`Set[str]` - `None`): Set of cookie names that should trigger the CSRF check if they are present in the request. Useful if you have other authentication methods that don't rely on cookies and don't need CSRF enforcement. If this parameter is `None`, the default, CSRF is **always** enforced.
* `safe_methods` (`Set[str]` - `{"GET", "HEAD", "OPTIONS", "TRACE"}`): HTTP methods considered safe which don't need CSRF protection.
* `cookie_name` (`str` - `csrftoken`): Name of the cookie.
* `cookie_path` `str` - `/`): Cookie path.
* `cookie_domain` (`Optional[str]` - `None`): Cookie domain. If your frontend and API lives in different sub-domains, be sure to set this argument with your root domain to allow your frontend sub-domain to read the cookie on the JavaScript side.
* `cookie_secure` (`bool` - `False`): Whether to only send the cookie to the server via SSL request.
* `cookie_samesite` (`str` - `lax`): Samesite strategy of the cookie.
* `header_name` (`str` - `x-csrftoken`): Name of the header where you should set the CSRF token.
## License
This project is licensed under the terms of the MIT license.
Raw data
{
"_id": null,
"home_page": "https://github.com/lainezdev/fastapi-csrf-jinja",
"name": "fastapi-csrf-jinja",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "fastapi, csrf, jinja, middleware",
"author": "Juan Lainez",
"author_email": "camilolainez@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/8d/2f/c6174d2259920812873c05a528757de0e5f69c3ec6953f80619cb12b0bb5/fastapi_csrf_jinja-0.1.3.tar.gz",
"platform": null,
"description": "# fastapi-csrf-jinja\n\n`fastapi-csrf-jinja` is a CSRF middleware for FastAPI applications that supports tokens in both headers and HTML forms. This library is based on `starlette-csrf`, with additional support for Jinja template integration.\n\n## How it works?\n\n1. The user makes a first request with a method considered safe (by default `GET`, `HEAD`, `OPTIONS`, `TRACE`).\n2. It receives in response a cookie (named by default `csrftoken`) which contains a secret value.\n3. When the user wants to make an unsafe request, the server expects them to send the same secret value in a header (named by default `x-csrftoken`). Additionally, the middleware now allows submission of the token via HTML forms using Jinja.\n4. The middleware compares the secret value provided in the cookie with the value in the header or form:\n * If they match, the request is processed.\n * Otherwise, a `403 Forbidden` error response is given.\n\n## Features\n- Supports CSRF tokens in headers and HTML forms.\n- Jinja template processor for easy CSRF token management in forms.\n\n## Installation\n\n```bash\npip install fastapi-csrf-jinja\n```\n\n## Usage with FastAPI\n\n```py\nfrom fastapi import FastAPI\nfrom fastapi.templating import Jinja2Templates\nfrom fastapi_csrf_jinja.middleware import FastAPICSRFJinjaMiddleware\nfrom fastapi_csrf_jinja.jinja_processor import csrf_token_processor\n\napp = FastAPI()\n\ncookie_name = \"your_cookie_name\"\nheader_name = \"your_header_name\"\n\napp.add_middleware(\n FastAPICSRFJinjaMiddleware, \n secret = \"your_secret\",\n cookie_name = cookie_name,\n header_name = header_name,\n )\n\ntemplates = Jinja2Templates(\n directory=\"templates\", \n context_processors=[csrf_token_processor(cookie_name, header_name)]\n )\n```\n\n- Defaults to `cookie_name` as `\"csrftoken\"` and `header_name` as `\"x-csrftoken\"` if not specified.\n\n## Usage with Jinja and HTML forms\n\nNow, the middleware integrates with a context processor, a function that returns a dictionary containing the CSRF token, CSRF input, and CSRF header for use with other tools such as HTMX.\n\nSimply using {{ csrf_input | safe }} in each form is now sufficient to ensure a more secure web application. For example:\n\n```html\n<form method=\"post\">\n {{ csrf_input | safe }}\n <!-- Other form fields here -->\n <button type=\"submit\">Submit</button>\n</form>\n```\n\nFurthermore, we can use {{ csrf_header }} in HTMX requests. For example:\n\n```html\n<form hx-patch=\"/route/edit\" hx-headers='{{ csrf_header | tojson | safe }}' hx-trigger=\"submit\" hx-target=\"#yourtarget\" hx-swap=\"outerHTML\" >\n <!-- Other form fields here -->\n <button type=\"submit\">Submit</button>\n</form>\n```\n\n## Arguments\n\n* `secret` (`str`): Secret to sign the CSRF token value. **Be sure to choose a strong passphrase and keep it SECRET**.\n* `required_urls` (`Optional[List[re.Pattern]]` - `None`): List of URL regexes that the CSRF check should **always** be enforced, no matter the method or the cookies present.\n* `exempt_urls` (`Optional[List[re.Pattern]]` - `None`): List of URL regexes that the CSRF check should be skipped on. Useful if you have any APIs that you know do not need CSRF protection.\n* `sensitive_cookies` (`Set[str]` - `None`): Set of cookie names that should trigger the CSRF check if they are present in the request. Useful if you have other authentication methods that don't rely on cookies and don't need CSRF enforcement. If this parameter is `None`, the default, CSRF is **always** enforced.\n* `safe_methods` (`Set[str]` - `{\"GET\", \"HEAD\", \"OPTIONS\", \"TRACE\"}`): HTTP methods considered safe which don't need CSRF protection.\n* `cookie_name` (`str` - `csrftoken`): Name of the cookie.\n* `cookie_path` `str` - `/`): Cookie path.\n* `cookie_domain` (`Optional[str]` - `None`): Cookie domain. If your frontend and API lives in different sub-domains, be sure to set this argument with your root domain to allow your frontend sub-domain to read the cookie on the JavaScript side.\n* `cookie_secure` (`bool` - `False`): Whether to only send the cookie to the server via SSL request.\n* `cookie_samesite` (`str` - `lax`): Samesite strategy of the cookie.\n* `header_name` (`str` - `x-csrftoken`): Name of the header where you should set the CSRF token.\n\n## License\n\nThis project is licensed under the terms of the MIT license.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "CSRF middleware for FastAPI applications with Jinja template integration.",
"version": "0.1.3",
"project_urls": {
"Documentation": "https://github.com/lainezdev/fastapi-csrf-jinja",
"Homepage": "https://github.com/lainezdev/fastapi-csrf-jinja",
"Repository": "https://github.com/lainezdev/fastapi-csrf-jinja",
"Source": "https://github.com/lainezdev/fastapi-csrf-jinja"
},
"split_keywords": [
"fastapi",
" csrf",
" jinja",
" middleware"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "6097c77974493e5ffab3d65f1b7d7e407a66e5fa96e2d0e987cd80b7f927f3c7",
"md5": "1152dca8545dca6aaf08f1e6fc5af73b",
"sha256": "4bde9ad70d7a6051201fa7663e761dbf730d6e2a8025f381c44c0c6b3385a69d"
},
"downloads": -1,
"filename": "fastapi_csrf_jinja-0.1.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "1152dca8545dca6aaf08f1e6fc5af73b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 6492,
"upload_time": "2024-06-06T19:25:27",
"upload_time_iso_8601": "2024-06-06T19:25:27.210645Z",
"url": "https://files.pythonhosted.org/packages/60/97/c77974493e5ffab3d65f1b7d7e407a66e5fa96e2d0e987cd80b7f927f3c7/fastapi_csrf_jinja-0.1.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "8d2fc6174d2259920812873c05a528757de0e5f69c3ec6953f80619cb12b0bb5",
"md5": "5fa88a8c2c22dd00959ec107cf5c9a33",
"sha256": "ac7d5931439d0b65f0a0f1df449547a4247996707ff21d04ed27b7ab623774de"
},
"downloads": -1,
"filename": "fastapi_csrf_jinja-0.1.3.tar.gz",
"has_sig": false,
"md5_digest": "5fa88a8c2c22dd00959ec107cf5c9a33",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 5993,
"upload_time": "2024-06-06T19:25:29",
"upload_time_iso_8601": "2024-06-06T19:25:29.401063Z",
"url": "https://files.pythonhosted.org/packages/8d/2f/c6174d2259920812873c05a528757de0e5f69c3ec6953f80619cb12b0bb5/fastapi_csrf_jinja-0.1.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-06-06 19:25:29",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "lainezdev",
"github_project": "fastapi-csrf-jinja",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "fastapi-csrf-jinja"
}