Authentication and CORS
I cannot sign in: email not verified
Section titled “I cannot sign in: email not verified”Sign-in needs a verified address. If email is not configured, the link is logged: run wrangler tail, request a new link, and open the URL from the log.
Better Auth URL is wrong
Section titled “Better Auth URL is wrong”pnpm run update -- --authExisting sessions can depend on the current authentication origin, so change it deliberately.
Browser reports a CORS error
Section titled “Browser reports a CORS error”Add your website’s origin to CORS_ORIGINS (comma-separated, exact scheme and host). It is a plain variable, not a secret. Set it under [vars] in the wrangler.toml at the root of your CMS project:
CORS_ORIGINS = "https://www.example.com,http://localhost:4321,https://your-admin.example.com"Keep the Admin Worker origin that setup already put there. Then redeploy the API for the change to apply:
wrangler deployA value edited only in the Cloudflare dashboard can be overwritten by the next deploy, so keep wrangler.toml as the source of truth. For local development, .dev.vars overrides this value.
This applies to a site using the same-origin proxy too. The proxy forwards the browser’s Origin header on sign-in and form requests, and the API checks it.
The Astro installer does not edit this for you. Setup adds the Admin Worker origin automatically.
Signed in, but the session does not stick
Section titled “Signed in, but the session does not stick”On a cross-site setup the session cookie is third-party, and some browsers block those. Use the same-origin proxy.
429 on sign-in or forms
Section titled “429 on sign-in or forms”Auth routes allow 10 POSTs per 60 seconds per IP, password reset and recovery 3, and forms 5. An auth 429 returns { "code": "TOO_MANY_REQUESTS", "message": … }. Behind a proxy, configure TRUSTED_PROXY_SECRET so the limit is per visitor rather than per proxy. This also shows up locally: without the secret in both projects’ .dev.vars, every request through your local /cms proxy shares one bucket, so a few test sign-ups or form posts in a row start returning 429. See Rate limiting.
Sign-up works but the account cannot sign in
Section titled “Sign-up works but the account cannot sign in”New accounts must verify their email first, and a website account has role none, which cannot use the admin. To give someone CMS access, an Owner or Admin sets their role under Users. See Users & Roles.
Sign-up returns TURNSTILE_REQUIRED or TURNSTILE_FAILED
Section titled “Sign-up returns TURNSTILE_REQUIRED or TURNSTILE_FAILED”TURNSTILE_SECRET_KEY is set on the API, so sign-up needs a Turnstile token (auth.signUp({ turnstileToken })). Tokens are single use: reset the widget after a failed attempt. See Astro authentication.