Skip to content

Auth, cookies and CORS

Sessions are better-auth cookies set by the API. For a front end to use them, three things must line up: the cookie’s domain, the origins the API trusts, and CORS. When they don’t, sign-in returns 200 and the very next request is signed out, with nothing in any log.

Signing in and landing back where you started · Open full screen ↗
API variable Controls
BETTER_AUTH_COOKIE_DOMAIN The session cookie’s Domain. Empty: the API’s own host. .example.com: shared by every subdomain
BETTER_AUTH_COOKIE_PREFIX The cookie’s name prefix. Keep it distinct per project on a shared domain
FRONTEND_HOST The front end’s origin: trusted by auth and allowed by CORS
MISC_CORS_ORIGINS More origins, comma-separated, trusted by auth and allowed by CORS. Full origins (http://localhost:3001) are used as written; bare hostnames (example.com) expand to https:// for the host and its auth., app. and admin. subdomains
BETTER_AUTH_URL The API’s public URL: callback URLs and email links

A browser drops any cookie whose domain doesn’t cover the host that set it: a Domain=.example.com cookie from api.example.com is kept, one from localhost isn’t.

API on localhost:5000, react-app on localhost:3000: the defaults.

FRONTEND_HOST='http://localhost:3000'
BETTER_AUTH_COOKIE_DOMAIN=''
  1. In the browser’s dev tools, look at the sign-in response’s Set-Cookie. A warning on it (“domain attribute invalid”) means the cookie domain doesn’t cover the host.
  2. Check the next request to the API carries the cookie. If not: the request isn’t credentialed (the templates’ clients always are), or the cookie’s domain or SameSite excludes it.
  3. A CORS error in the console means the page’s origin isn’t in the API’s CORS list for this environment.
  4. A redirect back to the login page after success means the redirect target isn’t a trusted origin: the front end falls back to its default.