Troubleshooting
Fixes for the problems people actually run into, grouped by where they show up.
Registering apps
"web clients require https redirect URIs on non-loopback hosts"
Production redirect URIs must use https://. For local development use http://localhost:PORT
or http://127.0.0.1:PORT: apps whose redirect URIs are all local are accepted as loopback
clients.
invalid_redirect_uri during sign-in
The redirect URI your app sends must match a registered one exactly: scheme, host, port,
path, and no trailing slash differences. With the SDK it's
APP_URL + /api/auth/webrizen/callback, so check APP_URL.
Signing in to an app
I sign in, get sent back, but I'm still signed out (local dev)
Both apps are on the same host (localhost), so their cookies collide. Serve the app from
127.0.0.1 and set APP_URL=http://127.0.0.1:4000, or use different hostnames.
?error=login_expired after signing in
The temporary sign-in cookie expired (10 minutes) or was set on a different host. Start again,
and make sure the address in the browser matches APP_URL.
A user's new role doesn't show up in the app
Tokens capture permissions at sign-in. Send the user to /api/auth/webrizen/refresh, or have
them sign in again. See Keeping permissions fresh.
org is null
The user doesn't belong to any organization yet, or your app didn't request the
organization scope. Invite them, and check your scopes.
Accounts and email
Verification codes never arrive
- Development: with
SMTP_HOSTempty, emails are printed in the terminal runningpnpm dev. Look there. - Production: check the SMTP credentials, and that SPF/DKIM are set so mail isn't marked as spam. The Vercel function logs show SMTP errors.
"Too many attempts. PIN sign-in is locked for 15 minutes."
Five wrong PINs lock PIN sign-in for 15 minutes. The person can still sign in with their password, a code or a passkey right away.
"Two-factor authentication is on for this account. Sign in with your password."
PIN sign-in is intentionally disabled for accounts with two-factor, so a PIN can't be used to skip it.
Passkeys stopped working after changing domains
Passkeys are bound to the domain in BETTER_AUTH_URL. People must add new passkeys on the new
domain; the old ones can be removed from Security.
Server
"Failed to decrypt private key"
BETTER_AUTH_SECRET changed after signing keys were created. Restore the original secret. If
that's impossible, delete the rows in the jwks table: new keys are created automatically,
and apps must sign users in again.
EACCES when starting the local database on Windows
Windows sometimes reserves port 5432. The local database therefore uses port 54320
(pnpm --filter @webrizen/accounts db:local), which matches the default DATABASE_URL.
Docker Desktop won't start (REGDB_E_CLASSNOTREG)
Windows Subsystem for Linux is damaged. You don't need Docker for Webrizen SSO: use
db:local. To repair WSL anyway, run wsl --update from an administrator terminal, or
reinstall "Windows Subsystem for Linux" from the Microsoft Store.
Still stuck?
Check the server logs first: every failed OIDC request logs a precise reason, such as
invalid_client, invalid_grant or invalid_redirect_uri. Then compare the discovery
document at /api/auth/.well-known/openid-configuration with your app's configuration.