Authentication errors

Fix sign-up 403s, rate-limited sign-ins, API keys with the wrong permissions, and stale sessions.

#Sign-up returns 403 signup_forbidden

#Problem

New users can't register. POST /api/auth/sign-up/email returns 403 with the error code signup_forbidden, even though the request body is valid.

#Cause

Self-registration is controlled by RBAC, not an environment variable. Sign-up is allowed only when the caller's role has the system/users:create permission. Unauthenticated callers are checked as the public role, which doesn't have this permission by default — so public sign-up is disabled out of the box.

The one exception is a fresh install: when no users exist yet, the first sign-up is always allowed so you can create the initial admin account.

#Fix

Choose the registration model you want:

  1. Open registration — grant system/users:create to the public role in the access control settings. Anyone can then sign up.
  2. Invite-only — keep the default. An admin whose role has system/users:create creates accounts through the user management UI or POST /api/v1/users.

#Prevention

Decide on your registration model when you set up the instance. Review which roles hold system/users:create after any role changes — granting it to public opens registration to everyone.

#Sign-in returns 429 rate_limited

#Problem

Sign-in attempts fail with 429 and the error code rate_limited. The response includes a Retry-After header.

#Cause

All /api/auth/* endpoints are rate limited to 5 requests per minute per IP address to protect against brute-force attacks. The counter is atomic (backed by a Durable Object) and persists across Worker restarts, so rapid retries don't reset it.

#Fix

  1. Wait for the number of seconds shown in the Retry-After response header, then try again.
  2. Check the X-RateLimit-Remaining header on auth responses to see how many attempts you have left in the current window.
  3. If your app retries failed sign-ins automatically, add a backoff so the retries don't consume the whole window.

#Prevention

Don't loop sign-in requests. Cache the session after a successful sign-in and reuse it — a session stays valid until it expires or is revoked, so there is no need to re-authenticate per request.

#Auth requests return 503 "Rate limiting unavailable"

#Problem

Requests to /api/auth/* fail with 503 and the message Rate limiting unavailable. Request blocked. Other API endpoints keep working.

#Cause

Authentication endpoints fail closed by design. If the rate-limiting infrastructure (the Durable Object and the KV fallback) is unreachable, EmuView blocks auth requests rather than allowing unlimited sign-in attempts. Non-auth endpoints fail open to preserve availability, which is why the rest of the API is unaffected.

#Fix

  1. Check the health of your Cloudflare Workers deployment — this usually indicates a missing or misconfigured RATE_LIMITER Durable Object binding or POLICY_CACHE KV binding.
  2. Verify both bindings exist in your wrangler.toml and redeploy.

#Prevention

Keep the Durable Object and KV bindings from the deployment template intact. Removing them doesn't disable rate limiting — it disables authentication.

#API key is denied actions it should be allowed to perform

#Problem

Requests authenticated with an API key return 403 forbidden for operations you expected the key to perform.

#Cause

An API key's permissions come from the RBAC role assigned to it. If you create a key without a roleId, it falls back to the built-in api role, which may not include the permissions you intended.

#Fix

  1. Create a new key with an explicit role: pass roleId in the body of POST /api/auth/api-keys.
  2. The role must belong to your project, and it can't be super_admin — API keys are never allowed that role.
  3. Check what the key's role can actually do with the Effective Access tab of the Access Inspector (System → Access), which shows effective CRUD permissions per resource for any user, role, or crew.

#Prevention

Assign a role explicitly whenever you create an API key. Create dedicated least-privilege roles for machine access instead of reusing broad user roles. See API keys for details.

#Role or session changes don't take effect immediately

#Problem

You changed a user's role, or updated authentication settings, but requests still behave as if the old configuration applies.

#Cause

Two caches are involved:

  • Sessions are cached for up to 5 minutes. Role changes made through the user management UI set a revocation flag that invalidates the cached session, but sessions changed by other means can stay stale until the cache expires.
  • Settings (including authentication settings such as trusted origins) are cached for up to 60 seconds.

#Fix

  1. For a stale session, have the affected user sign out and sign back in — signing out deletes the cached session immediately.
  2. For stale settings, wait up to a minute and retry.

#Prevention

Make role changes through the user management UI so revocation flags are set for you. When testing configuration changes, allow the cache windows above before concluding a change didn't work.