Security boundaries
This page describes the boundaries auth4.dev enforces and what remains your responsibility. It describes the design. It is not a compliance certification or audit report.
Project isolation
- Every project is a separate tenant with its own issuer,
https://auth.auth4.dev/t/{projectId}. Every stored record, one-time code and session key includes the project ID. - Tokens carry the issuer and a
tenant_idclaim. The server SDK rejects tokens whose issuer or project doesn't match its configuration. - Codes, proofs, device codes and refresh tokens from one project or application can't be used with another.
- The project is taken from the request path or parameters, never from the request host.
Console and management separation
- Developer console accounts live in a separate, reserved realm, with their own audience (
urn:auth4:management). It can't be reconfigured. - Player tokens, including guest tokens, never authorize management operations, and management tokens are rejected by the server SDK.
- Console tokens stay on the console's own server. The console page uses a session cookie that scripts can't read.
- Owners, admins and viewers have different permissions, and every management request is authorized against the project in its path.
Protocol choices
- Authorization code with S256 PKCE only. Implicit, hybrid and password grants are refused.
- Redirect URIs are compared exactly. Wildcards, fragments and auth4.dev's own origins are rejected.
- Authorization codes last 60 seconds and are consumed before PKCE is checked, so a wrong verifier can't be retried.
- Access and ID tokens are RS256, last five minutes, and are validated separately. An ID token isn't accepted as an access token.
- Refresh tokens rotate on every use. Reuse revokes the whole family.
- Browser and game applications are public clients with no secrets to leak.
Hosted login and approval pages
- Sign-in, consent, device approval and guest upgrade run on the auth origin, so your application never handles email codes or Discord credentials.
- Flow and session cookies use the
__Host-prefix and areSecure,HttpOnlyandSameSite=Lax. - State-changing requests check the exact
Origin. Device approval also requires a per-flow CSRF token. - Project branding is limited to an allowlist and rendered as text. The guest upgrade window accepts messages only from your application's registered origins.
Secrets and personal data
- Email codes are stored only as keyed hashes and are never logged.
- Discord client secrets are encrypted at rest, write-only in the console, and used only on the server.
- Rate limits are counted against pseudonymized identifiers, not raw IP or email addresses.
- Security decisions (codes, sessions, refresh families and rate limits) use strongly consistent storage, never eventually consistent caches.
- Error responses and logs don't include provider responses, tokens or secrets.
Your responsibilities
- Verify every access token on your server with a configured issuer, project and audience.
- Allow for the five-minute revocation window in sensitive actions.
- Register only redirect URIs and origins you control, and remove ones you no longer use.
- Persist native refresh tokens only through a real OS-protected secure store.
- Keep tokens out of URLs, logs, analytics and crash reports.
- Protect your Discord client secret and rotate it if it leaks.
- Give only the people who need it owner access to your project.