Skip to content

Authentication and CORS

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.

Terminal window
pnpm run update -- --auth

Existing sessions can depend on the current authentication origin, so change it deliberately.

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:

Terminal window
wrangler deploy

A 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.

On a cross-site setup the session cookie is third-party, and some browsers block those. Use the same-origin proxy.

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.