Securealy
Check · Security · high · local

Auth settings are closed by default

Signup matches intent, minimum password is 12 or more, OTP expiry and redirect allow-list are set, anonymous sign-ins off.

Severity
high
Tier
Local: runs on your machine with your own keys
Category
Security
Fix
Summary below; full runbook in the Fix Kit, Module 05: Users and access
Id
supabase-auth-config

What this means

Passing means the settings on your auth provider match what you intend: signup is closed unless you sell self-serve signup, the minimum password length is 12 or more, the code expiry and the redirect allow-list are set, and anonymous sign-ins are off. Failing means one of them is open in a way your code never shows. The repository can be perfect and the door still be open.

How we test it

This check runs on your own machine through the CLI with a Supabase management token (your avatar, Account, Access Tokens) in your environment; it reads GET https://api.supabase.com/v1/projects/YOUR_PROJECT_REF/config/auth and never prints the token. It reports disable_signup, password_min_length, mailer_otp_exp, uri_allow_list and external_anonymous_users_enabled. Pass is signup matching your stated intent, a minimum of 12, an allow-list that is not empty, and anonymous sign-ins off. Warn is an empty allow-list or an OTP expiry you have not set. Fail is open signup you did not intend, a minimum under 12, or anonymous sign-ins on.

Why it matters

Auth provider settings are attack surface the code never shows. In the Fix Kit's own estate, open signup was enabled on the auth provider for months with a six-character minimum password, so anyone with the public key in page source could create an account; they got no grant and saw nothing, but the claim that the domain gate was the only door was false the whole time. An empty redirect allow-list is how a person invited to one client's dashboard was enrolled in another's two-factor setup: the rejected redirect fell back to the site URL.

The fix

Read the current values with the management API, then PATCH https://api.supabase.com/v1/projects/YOUR_PROJECT_REF/config/auth to disable_signup: true (false only for intended self-serve), password_min_length: 12, jwt_exp: 1800, a neutral site_url, a uri_allow_list holding every login URL with a /** suffix, mailer_otp_exp: 604800, mailer_autoconfirm: false and external_anonymous_users_enabled: false, exactly as Module 5's templates/supabase-auth-settings.md lists them. Never lower mailer_otp_exp while invite codes are outstanding, because expiry is evaluated at verify time against the current value, and confirm afterwards with bash MODULE-03-lock-it-down/templates/audit.sh auth. The full runbook is in the Fix Kit, Module 05.

Prompt for your AI

Paste this into the coding agent that built the app. It reproduces the finding and stops before changing anything; the fix steps are in the kit.

Load SUPABASE_PROJECT_REF and SUPABASE_MGMT_TOKEN from .env.local; never print either.
Run once: curl -s "https://api.supabase.com/v1/projects/$SUPABASE_PROJECT_REF/config/auth" -H "Authorization: Bearer $SUPABASE_MGMT_TOKEN" | jq '{disable_signup, password_min_length, jwt_exp, site_url, uri_allow_list, mailer_otp_exp, mailer_autoconfirm, external_anonymous_users_enabled}' and show me the output.
Tell me whether this app has a self-serve signup flow by reading the login and signup pages, so we know what disable_signup should be.
List every login URL in the app and compare it with uri_allow_list; name any login URL that is missing.
Do not PATCH any setting; list each field whose value differs from Module 5's templates/supabase-auth-settings.md and stop.
Run `bash MODULE-03-lock-it-down/templates/audit.sh auth` once and show me the output; expected for a passing project: auth: 0 failures.

Next

Grade your own URL

Every grade lists this check with its evidence for your site. Two free grades a day.