microdot.csrf — CSRF protection¶
Rejects state-changing requests that originate cross-site. The check
runs as a before_request hook and uses the browser-supplied
Sec-Fetch-Site header (with the Origin header as a fallback for
older browsers, when paired with a microdot.cors.CORS
instance).
class CSRF¶
- class microdot.csrf.CSRF(app: Microdot | None = None, cors=None, protect_all: bool = True, allow_subdomains: bool = False)¶
- app
The
microdot.Microdotinstance to install on. Optional; callinitialize()later if not given.- cors
The
microdot.cors.CORSinstance that defines the application’s trusted origins. Required for falling back to theOriginheader on browsers that do not sendSec-Fetch-Site. Optional; without it, only theSec-Fetch-Sitecheck applies.- protect_all
If
True(default), every route exceptGET,HEAD, andOPTIONSis protected automatically. Routes can be exempted individually withexempt(). IfFalse, no routes are protected by default and individual routes opt in withprotect().- allow_subdomains
If
True, requests from subdomains of the application’s origins are accepted (same-siteSec-Fetch-Site, or matching origin suffix).
- exempt(f)¶
Decorator that exempts a route from CSRF protection. Place it directly after the route decorator:
@app.post('/webhook') @csrf.exempt async def webhook(request): # accepts cross-site POSTs
- protect(f)¶
Decorator that forces CSRF protection on a route that would otherwise be exempt (e.g. a
GETroute or every route whenprotect_all=False).
Example:
from microdot import Microdot
from microdot.cors import CORS
from microdot.csrf import CSRF
app = Microdot()
cors = CORS(app, allowed_origins=['https://app.example.com'])
csrf = CSRF(app, cors=cors)
@app.post('/api/save')
async def save(request):
# automatically CSRF-protected
return {'ok': True}
A request is allowed when Sec-Fetch-Site reports same-origin or
none (or same-site when allow_subdomains=True). If the
header is absent, the request’s Origin is matched against the CORS
allow-list. Requests with neither header are accepted (typical for
direct API calls that aren’t subject to browser CSRF).