-
Notifications
You must be signed in to change notification settings - Fork 68
Howto CSRF tokens
Bindery v1.0 replaces the X-Requested-With header check with a double-submit CSRF token on all session-cookie-authenticated mutations (POST, PUT, PATCH, DELETE).
Browser users: the UI handles this transparently — no action needed.
API-key users: CSRF is not required. X-Api-Key requests bypass the check entirely. Existing automation continues to work without changes.
Scripts using session cookies: read on.
You need a token if your script:
- Authenticates with a
bindery_sessioncookie (e.g., you logged in via the browser and grabbed the cookie), and - Makes any mutating request (
POST,PUT,PATCH,DELETE)
If you're using X-Api-Key, skip this page — you're already exempt.
TOKEN=$(curl -s \
-b "bindery_session=<your-session-cookie>" \
http://bindery:8787/api/v1/auth/csrf \
| jq -r .token)Tokens are per-session and do not expire between requests in the same session. Fetch once, reuse for the session lifetime.
Pass it as the X-CSRF-Token header on every mutating request:
curl -X POST http://bindery:8787/api/v1/author \
-b "bindery_session=<your-session-cookie>" \
-H "X-CSRF-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Ursula K. Le Guin"}'#!/usr/bin/env bash
BINDERY=http://bindery:8787
COOKIE="bindery_session=<your-session-cookie>"
# 1. Fetch CSRF token
TOKEN=$(curl -s -b "$COOKIE" "$BINDERY/api/v1/auth/csrf" | jq -r .token)
# 2. Use it on the mutation
curl -X POST "$BINDERY/api/v1/author" \
-b "$COOKIE" \
-H "X-CSRF-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Ursula K. Le Guin"}'If your script was using X-Requested-With: XMLHttpRequest (the pre-v1.0 CSRF bypass), switch to X-Api-Key:
# Before (v0.x)
curl -X POST http://bindery:8787/api/v1/author \
-b "bindery_session=<cookie>" \
-H "X-Requested-With: XMLHttpRequest" \
...
# After — option A: switch to API key (simplest, recommended)
curl -X POST http://bindery:8787/api/v1/author \
-H "X-Api-Key: <your-api-key>" \
...
# After — option B: keep session cookie, add CSRF preflight
TOKEN=$(curl -s -b "bindery_session=<cookie>" http://bindery:8787/api/v1/auth/csrf | jq -r .token)
curl -X POST http://bindery:8787/api/v1/author \
-b "bindery_session=<cookie>" \
-H "X-CSRF-Token: $TOKEN" \
...Option A is simpler and recommended for automation. Your API key is in Settings → My Account → API Key.
| Symptom | Cause | Fix |
|---|---|---|
403 Forbidden on mutations that worked before v1.0 |
Script uses session-cookie auth but doesn't send X-CSRF-Token
|
Switch to X-Api-Key, or add the CSRF preflight (see above) |
403 even with X-CSRF-Token present |
Token was fetched with a different session cookie than the one used on the mutation | Fetch the token and make the mutation with the same bindery_session cookie value |
401 Unauthorized on GET /api/v1/auth/csrf
|
Session cookie is expired or invalid | Log in again to get a fresh session cookie |
X-Requested-With: XMLHttpRequest stopped working |
Removed in v1.0 | Switch to X-Api-Key or use the CSRF token flow |
See also: docs/multi-user.md — CSRF tokens | Troubleshooting
Getting started
Setup guides
How-to guides — proxy auth (v1.0)
How-to guides — OIDC (v1.0)
- Google Sign-In
- GitHub OAuth via Dex
- Authelia as OIDC provider
- Authentik
- Keycloak
- Rotate OIDC client secrets
- Recover from broken OIDC
How-to guides — multi-user (v1.0)
Reference
Contributing