Starlette middleware implementing Double Submit Cookie technique to mitigate CSRF.
GET
, HEAD
, OPTIONS
, TRACE
).csrftoken
) which contains a secret value.x-csrftoken
).403 Forbidden
error response is given.This mechanism is necessary if you rely on cookie authentication in a browser. You can have more information about CSRF and Double Submit Cookie in the OWASP Cheat Sheet Series.
pip install starlette-csrf
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette_csrf import CSRFMiddleware
routes = ...
middleware = [
Middleware(CSRFMiddleware, secret="__CHANGE_ME__")
]
app = Starlette(routes=routes, middleware=middleware)
from fastapi import FastAPI
from starlette_csrf import CSRFMiddleware
app = FastAPI()
app.add_middleware(CSRFMiddleware, secret="__CHANGE_ME__")
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.By default, a plain text response with the status code 403 is returned when the CSRF verification is failing. You can customize it by overloading the middleware class and implementing the _get_error_response
method. It accepts in argument the original Request
object and expects a Response
. For example:
from starlette.requests import Request
from starlette.responses import JSONResponse, Response
from starlette_csrf import CSRFMiddleware
class CustomResponseCSRFMiddleware(CSRFMiddleware):
def _get_error_response(self, request: Request) -> Response:
return JSONResponse(
content={"code": "CSRF_ERROR"}, status_code=403
)
We use Hatch to manage the development environment and production build. Ensure it's installed on your system.
You can run all the tests with:
hatch run test
Execute the following command to apply linting and check typing:
hatch run lint
This project is licensed under the terms of the MIT license.