From 866395bf0ca4c90571ac4ed81dfe8bb4cf9f500c Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Fri, 12 Jun 2026 14:36:02 +0000 Subject: [PATCH] fix(auth): stop falsely rejecting every signup as "already registered" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With email confirmation enabled, Supabase returns an IDENTICAL response for a brand-new email and an already-registered one (no error, no session, null user via supabase-js) — by design, to prevent email enumeration. The previous heuristic treated that null-user/no-session shape as "already registered" and 409'd EVERY signup, even though the confirmation email was actually sent. Remove the impossible detection: when signUp succeeds with no session, just report needsEmailConfirmation (the signup page already shows "check your email"). A returned session still signs the user in immediately. Verified against the live project: a fresh email and an existing one both return { user: null, session: null, error: null } via supabase-js. Co-Authored-By: Claude Opus 4.8 --- apps/web/src/app/api/auth/signup/route.ts | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/apps/web/src/app/api/auth/signup/route.ts b/apps/web/src/app/api/auth/signup/route.ts index 88dc75a..101c16b 100644 --- a/apps/web/src/app/api/auth/signup/route.ts +++ b/apps/web/src/app/api/auth/signup/route.ts @@ -15,22 +15,14 @@ export async function POST(req: NextRequest) { if (error) return Response.json({ error: error.message }, { status: 400 }); - // Supabase obfuscates an already-registered email when confirmations are on: - // it returns no error, no session, and either a null user or a user with - // empty identities. (A real new signup that returns a session is fine.) - const alreadyRegistered = !data.session && (!data.user || (data.user.identities?.length ?? 0) === 0); - if (alreadyRegistered) { - console.warn(`[auth] signup obfuscated/no-user for ${email} — likely already registered (session=${!!data.session})`); - return Response.json( - { error: 'This email is already registered. Sign in instead, or use “forgot password”. If you never confirmed your email, request a new confirmation link.' }, - { status: 409 }, - ); - } - - if (!data.user) return Response.json({ error: 'no user returned' }, { status: 500 }); - + // With email confirmation enabled, Supabase deliberately returns an IDENTICAL + // response for a brand-new email and an already-registered one — no error, no + // session, and (via supabase-js) a null user — to prevent email enumeration. + // We therefore can't (and must not) tell the user "already registered"; we + // just report that a confirmation email is on its way. If a session IS present + // (confirmation disabled), the user is signed in immediately. const payload = { - user: { id: data.user.id, email: data.user.email }, + user: data.user ? { id: data.user.id, email: data.user.email } : null, session: data.session && { access_token: data.session.access_token, refresh_token: data.session.refresh_token,