Demo, all content is generated
Question

signUp works but my app says 'Signup failed', then 'User already registered'

Solved · 694 views · asked by adaeze · edited

New users see 'Signup failed, try again'. When they try again they get 'User already registered'. And some of them tell me they got a confirmation email anyway?? The code Claude wrote:

const { data, error } = await supabase.auth.signUp({ email, password })
if (error || !data.session) {
  setError('Signup failed, try again')
  return
}
navigate('/dashboard')

error is null, data.user is there, data.session is null. Claude says the session is null because Supabase is misconfigured.

What I’ve tried

Turned off 'Confirm email' in Supabase and then it works, but then anybody can sign up with someone else's email. Turned it back on.

Comment
Is 'Confirm email' enabled in Authentication → Providers → Email? That decides whether signUp returns a session. jb_supa · edited
Yes it is on adaeze · edited

3 answers

Marked as helpful by the asker
hannah_reyes · edited

Nothing is misconfigured. With Confirm email on, signUp creates the user and sends the email, but gives no session until they click the link. session: null is the success case here.

So change the flow:

const { data, error } = await supabase.auth.signUp({
  email, password,
  options: { emailRedirectTo: `${window.location.origin}/welcome` },
})
if (error) return setError(error.message)
if (!data.session) return setStep('check-your-inbox')
navigate('/dashboard')

The 'User already registered' on the second try is simply because the first try worked.

One subtle thing: when someone signs up with an email that already exists and is confirmed, Supabase returns a user object with an empty identities array instead of an error, so attackers can't use signup to find out who has an account. Show the same 'check your inbox' message in that case too.

Comment
Oh wow, so it was working the whole time and my own code said it failed. Changed it, added a check-your-inbox screen. Claude was so confident it was Supabase lol adaeze · edited
Nice example for 'make the model read the docs of the function it calls'. Pasting the signUp docs into the chat would have found it. sergio_ruiz · edited
jb_supa · edited

For the people who are stuck now: give the inbox screen a 'resend email' button:

await supabase.auth.resend({ type: 'signup', email })

and make sure /welcome (your emailRedirectTo) is in the Redirect URLs allow-list, otherwise the confirm link sends them to your Site URL.

Comment
sofia_gr · edited

And please keep Confirm email on, as you did. Without it, anyone can create accounts in other people's names, and your transactional mail to those addresses will hurt your sender reputation.

Comment