├── LICENSE ├── README.md └── csrf_middleware.py /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, Nathaniel Sabanski 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Why you may not need a CSRF Middleware in 2022 2 | 3 | Recent cookie enhancements can solve CSRF for you: 4 | 5 | 1. Set one cookie to "lax", set one cookie to "strict". 6 | 2. Check for the "strict" cookie whenever there's a database write (or other sensitive action). 7 | 8 | The "strict" cookie will not exist in situations where CSRF will be a threat. 9 | 10 | ### References 11 | 12 | * https://scotthelme.co.uk/csrf-is-dead/ 13 | * https://scotthelme.co.uk/csrf-is-really-dead/ 14 | * https://simonwillison.net/2021/Aug/3/samesite/ 15 | * Discussion: https://github.com/encode/starlette/discussions/1411 16 | 17 | ### Thanks for coming. 🤔 However if you still wish to use a middleware for some reason, please continue! 18 | 19 | # csrf-starlette-fastapi 20 | Dead simple CSRF security middleware for Starlette ⭐ and Fast API ⚡ 21 | 22 | * Will work with either a `` field or ajax request headers, interchangeably. 23 | * Uses stateless [Double Submit Cookie](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#double-submit-cookie) method, like Django. 24 | * Tiny, easy to audit. 25 | 26 | ### Install 27 | 28 | Add `csrf_middleware.py` to your project `/middleware` folder. 29 | 30 | ### Add to Starlette 31 | 32 | ```py 33 | from starlette.applications import Starlette 34 | from starlette.middleware import Middleware 35 | from middleware.csrf_middleware import CSRFMiddleware 36 | 37 | routes = ... 38 | 39 | middleware = [ 40 | Middleware(CSRFMiddleware) 41 | ] 42 | 43 | app = Starlette(routes=routes, middleware=middleware) 44 | ``` 45 | ### Add to FastAPI 46 | 47 | ```py 48 | from fastapi import FastAPI 49 | from middleware.csrf_middleware import CSRFMiddleware 50 | 51 | app = FastAPI() 52 | app.add_middleware(CSRFMiddleware) 53 | ``` 54 | ### Usage 55 | * Directly with HTML. 56 | * Pass `request.state.csrftoken` to your [template engine](https://www.starlette.io/templates/). 57 | * `` 58 | * Using [htmx](https://htmx.org/) ♥️: `
` 59 | * Using Javascript frameworks: `headers: { 'csrftoken': '{{ csrftoken }}' }` 60 | * [XMLHttpRequest.setRequestHeader()](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader) 61 | 62 | ### Why? 63 | 64 | To make available something more simple and auditable than the typical libraries for this as of 2022: 65 | * https://github.com/simonw/asgi-csrf 66 | * https://github.com/frankie567/starlette-csrf 67 | * https://github.com/piccolo-orm/piccolo_api/blob/master/piccolo_api/csrf/middleware.py 68 | -------------------------------------------------------------------------------- /csrf_middleware.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | from starlette.middleware.base import BaseHTTPMiddleware 3 | from starlette.responses import PlainTextResponse 4 | 5 | class CSRFMiddleware(BaseHTTPMiddleware): 6 | """ 7 | CSRF / Cross Site Request Forgery Security Middleware for Starlette and FastAPI. 8 | 1. Add this middleware using the middleware= parameter of your app. 9 | 2. request.state.csrftoken will now be available. 10 | 3. Use directly in an HTML