Metadata-Version: 2.1
Name: fastapi-csrf-protect
Version: 0.0.2
Summary: Simple integration of Cross-Site Request Forgery (XSRF) Protection by using either Cookies or Context combined with Headers
Home-page: UNKNOWN
License: UNKNOWN
Platform: UNKNOWN
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Description-Content-Type: text/markdown
Requires-Dist: fastapi (~=0.61.2)
Requires-Dist: itsdangerous (~=1.1.0)
Requires-Dist: pydantic (~=1.7.2)
Provides-Extra: dev
Requires-Dist: pytest (>=3.7) ; extra == 'dev'

# FastAPI CSRF Protect

## Features

---

FastAPI extension that provides Cross-Site Request Forgery (XSRF) Protection support (easy to use and lightweight).
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

```bash
pip install fastapi-csrf-protect
```

## Usage

---

### With Context and Headers

```python
from fastapi import FastAPI, Request, Depends
from fastapi.responses import ORJSONResponse
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'

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

@app.get('/form')
def form(request: Request, csrf_protect:CsrfProtect = Depends()):
  '''
  Returns form template.
  '''
  csrf_token = csrf_protect.generate_csrf()
  response = templates.TemplateResponse('form.html', { 'request': request, 'csrf_token': csrf_token })
  return response

@app.post('/posts', response_class=ORJSONResponse)
def create_post(request: Request, csrf_protect:CsrfProtect = Depends()):
  '''
  Creates a new Post
  '''
  csrf_token = csrf_protect.get_csrf_from_headers(request.headers['X-CSRFToken'])
  csrf_protect.validate_csrf(csrf_token)
  # Do stuff

@app.exception_handler(CsrfProtectError)
def csrf_protect_exception_handler(request: Request, exc: CsrfProtectError):
  return ORJSONResponse(status_code=exc.status_code, content={ 'detail':  exc.message }) # Bad Request

```

### With Cookies

```python
from fastapi import FastAPI, Request, Depends
from fastapi.responses import ORJSONResponse
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'

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

@app.get('/form')
def form(request: Request, csrf_protect:CsrfProtect = Depends()):
  '''
  Returns form template.
  '''
  response = templates.TemplateResponse('form.html', { 'request': request })
  csrf_protect.set_csrf_cookie(response)
  return response

@app.post('/posts', response_class=ORJSONResponse)
def create_post(request: Request, csrf_protect:CsrfProtect = Depends()):
  '''
  Creates a new Post
  '''
  csrf_protect.validate_csrf_in_cookies(request)
  # Do stuff

@app.exception_handler(CsrfProtectError)
def csrf_protect_exception_handler(request: Request, exc: CsrfProtectError):
  return ORJSONResponse(status_code=exc.status_code, content={ 'detail':  exc.message }) # Bad Request

```

## License

---

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


