Guide: Cookie auth¶
Switch the basic app from JSON token delivery to cookie delivery, with the CSRF client pattern. No providers change — only config and the client.
Config¶
auth = FastAuth(FastAuthConfig(
...,
token_delivery="cookie",
cookie_samesite="lax", # default
# cookie_secure defaults to (not debug): True in prod, False in dev
# debug=True, # uncomment to make cookies work over http://localhost
))
After register/login, the response carries three Set-Cookie headers (access_token, refresh_token, csrf_token) and the body is {"message": "Authentication successful"}.
Browser-side¶
async function login(email, password) {
await fetch("/auth/login", {
method: "POST",
credentials: "include", // important: send and accept cookies
headers: {"Content-Type": "application/json"},
body: JSON.stringify({email, password}),
});
// csartifact_token cookie is readable by JS:
window.__csrf = getCookie("csrf_token");
}
async function callProtected(route) {
return fetch(route, {
credentials: "include",
headers: {"X-CSRF-Token": window.__csrf},
});
}
function getCookie(name) {
return document.cookie.split("; ").map(c => c.split("="))
.find(([k]) => k === name)?.[1];
}
Refresh with cookies¶
await fetch("/auth/refresh", {
method: "POST",
credentials: "include",
headers: {"X-CSRF-Token": window.__csrf},
});
If the body is empty, /auth/refresh reads the refresh cookie and runs the CSRF check. (Posting a JSON {"refresh_token": "..."} skips CSRF — only do that if you've moved the refresh token out of the cookie.)
CORS¶
Cross-origin SPAs need cors_origins:
The middleware is added with allow_credentials=True. Never use ["*"] with credentials — browsers reject it.
Testing¶
TestClient stores cookies between calls when used as a context manager:
from fastapi.testclient import TestClient
def test_login_and_protected(app, client):
with TestClient(app) as c:
r = c.post("/auth/login", json={"email": "a@b.com", "password": "s3cur3!"})
assert r.status_code == 200
csrf = c.cookies["csrf_token"]
r2 = c.post("/api/submit", json={"x": 1}, headers={"X-CSRF-Token": csrf})
assert r2.status_code == 200
See Cookie delivery for the full reference.