Authentication (account API)
The dashboard session-cookie auth model, the 8s timeout, origin enforcement, and sanitized error forwarding for /dashboard/api/dashboard/* routes.
The account-management API (/dashboard/api/dashboard/*) authenticates with the dashboard session cookie — the same cookie issued during passwordless login. The proxy reads the cookie, injects it as the X-Session-Token header, and forwards the request to the backend. The public-API key (X-API-Key) is not accepted on any account-management route.
Every route under /dashboard/api/dashboard/* requires the session cookie. The full route catalog — grouped by resource (User, Apps, Credentials, Groups, Notifications, Billing, Configuration) — is in Account API reference.
Session cookie issuance
When you authenticate via the passwordless flow (send /signin from Signal, SimpleX, or Session; receive an 8-character code; enter it at the access-code page), the backend issues a session token and sets it as an HTTP-only cookie named session.
A missing or expired session cookie returns 400 { success: false, error: "Session token is required" }. Every account-management route requires the cookie; there is no anonymous read access.
Cookie-to-header translation
The proxy forwards the session cookie value as the X-Session-Token header to the backend. The cookie value is the session token — the proxy moves it from one HTTP mechanism to another so the backend’s auth middleware can match it. No re-wrapping, no decryption, no intermediate transformation.
Request timeout
Outbound calls to the backend time out at 8 seconds. A backend response exceeding 8 seconds returns 504 Gateway Timeout. Network failures (DNS, connection refused) return 502 Bad Gateway. Both are returned as JSON { error: "..." } with a sanitized message — never raw exception text or stack traces.
Allowlist-only routing
Every writable route is an explicit entry on the proxy’s allowlist. Requests to paths outside the allowlist return 404. The proxy has no ?url= passthrough, no OPTIONS handler, and no catch-all. The route catalog is documented in Account API reference.
Origin enforcement
POST, PUT, and DELETE requests must be same-origin. The proxy checks the Origin header against the request host and returns 400 { error: "Cross-origin requests are not allowed" } on mismatch.
A missing Origin header is permitted — non-browser clients (scripts, CI workers) that omit Origin pass the check. Scripts that send Origin: https://privacyflow.app (or omit it) work fine.
Error forwarding
The proxy forwards backend JSON error bodies verbatim when parseable — real messages like "name is required" or "credential not found" reach the client. Non-JSON responses are replaced with a generic "Backend request failed (status)" message. HTTP status codes pass through: a backend 404 returns 404 to the client.
Scripting the account-management API
- Authenticate once via the passwordless flow and capture the
sessioncookie. The cookie is HTTP-only — capture it from the dev-tools Application → Cookies panel or from theSet-Cookieresponse header during sign-in. - Send the cookie as a
Cookie: session=...header on every call to/dashboard/api/dashboard/*. - Re-authenticate on
400 { error: "Session token is required" }or any401. Cookies expire; there is no refresh token.
List apps
SESSION='session=xyz123abc...'
curl -s "https://privacyflow.app/dashboard/api/dashboard/apps" \
-H "Cookie: $SESSION" \
-H "Accept: application/json"
Returns the items[] array with one entry per app.
Create an app
curl -s -X POST "https://privacyflow.app/dashboard/api/dashboard/apps" \
-H "Cookie: $SESSION" \
-H "Origin: https://privacyflow.app" \
-H "Content-Type: application/json" \
-d '{
"name": "Support — Signal",
"protocol": ["signal"],
"deliveryType": "poll",
"status": "active"
}'
POST, PUT, and DELETE require the Origin header set to the dashboard host (or any same-origin value). Content-Type: application/json is required on all POST/PUT/DELETE requests, including those with an empty body.
Session security
The session cookie carries full dashboard authority — app creation, credential rotation, billing, and account mutations. Public-API keys are scoped to the messaging surface (/api/v1/*) and have no path into /dashboard/*.
Treat the session cookie as a long-lived privileged credential:
- Store it in a secrets manager, not in source control or logs.
- Scope it to the smallest set of scripts that require account mutations.
- Rotate it (sign out + re-authenticate) on any suspected exposure.
Warning
The session cookie grants the same authority as a dashboard login. A leaked cookie allows an attacker to create credentials, delete apps, modify billing, and rotate account state. Rotate immediately on exposure.