supabase / supabase-js

An isomorphic Javascript client for Supabase. Query your Supabase database, subscribe to realtime events, upload and download files, browse typescript examples, invoke postgres functions via rpc, invoke supabase edge functions, query pgvector.
https://supabase.com
MIT License
2.83k stars 219 forks source link

Enabling Post-Signup Email Verification without Blocking User Sign-In on Supabase (Resend) #991

Open SergejSi opened 1 month ago

SergejSi commented 1 month ago

Bug report

Describe the bug

I am trying to improve the user experience in my application by allowing users to sign in immediately after registration, even before verifying their email. The default behavior in Supabase requires users to verify their email before they can sign in, which I believe creates a poor user experience. I want to give users the ability to verify their email after they have signed in by sending them a verification link or preferably a code to verify their email. However, I'm facing an issue where I cannot send a verification link to users using the Supabase Auth resend method for this purpose.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Initialize Supabase auth with a user's email and password.
  2. Try to send the user a verification email after sign-up (not blocking sign-in) using the resend method as follows:
    await supabase.auth.resend({
        email: user?.email as string,
        type: "signup"
    });
  3. Notice that no verification email is received.

Expected behavior

I expect to be able to send users a verification email (or ideally a verification code) after they have signed up and signed in, without blocking their initial sign-in due to unverified email. This approach aims to enhance the user experience by not forcing email verification before the user can explore the application.

Additional context

This issue is critical for user onboarding and directly impacts the user experience in our application. If there's an alternative approach to achieve this behavior or if someone has solved a similar issue, insights would be greatly appreciated. Ideally, I would like to send a verification code that users can enter to verify their email, but currently, the primary issue is the inability to resend the verification link after the user signs in.

utkarsh1097 commented 1 month ago

I believe you have set Confirm email: Users will need to confirm their email address before signing in for the first time. to false. If that is the case, the user email is considered "verified" (you can confirm this by looking at the user.email_confirmed_at field. It is null when the email has not been verified and has some value when it is. Any user that registered when the Confirm email setting was set to off, will have their email_confirmed_at value close to the created_at timestamp.

If you want to implement "mail verification post sign-up" I would recommend using a custom metadata attribute (maybe a key like email_verified) which can be true/false depending on whether the mail is verified or not. But then you would have to implement your email verification API (whose responsibility would be to keep track of the verification tokens and set email_verified to true).

Edit: For reference, this is how Supabase's resend API works: https://github.com/supabase/auth/blob/master/internal/api/resend.go#L64-L172

devjume commented 1 month ago

+1 For this feature.

According to docs this have been possible but is deprecated? But I couldn't find more when, why and in what PR. And I cannot find any information what "Allow unverified email sign in" setting is/was.

image

There is old issue for this without update https://github.com/supabase/auth/issues/453

devjume commented 1 month ago

I had idea for hacky workaround which should be possible. But I didn't properly test this! See bottom

  1. Set "Confirm email" to false
  2. Sign up user with supabase.auth.signUp()
  3. Create database triggers that call supabase edge function Supabase youtube - Database Webhooks and Edge Functions
  4. On the edge function do:
    
    const { data, error } = await supabase.auth.admin.generateLink({
    type: 'magiclink', <---- NOTE: 'signup' wont work here.
    email: 'email@example.com'
    })

[PREVIOUS RETURNS OTP TOKEN]

Next use your own transaction email provider (AWS SES, Resend etc.) to send that token to the users email...

5. Create input to confirm OTP token. Then verify the token and confirm user email on backend.

const { data, error } = await supabase.auth.verifyOtp({ email, token, type: 'email'})

const { data: user, error } = await supabase.auth.admin.updateUserById( '6aa5d0d4-2a9f-4483-b6c8-0cf4c6c98ac4', { email_confirm: true } )


I didn't test this properly because it would require me to set webhooks and triggers manully on production. Because on production and local development webhook url is different.

Production: https://XXXX.supabase.co/functions/v1/hello-world Local env: http://host.docker.internal:54321/functions/v1/hello-world


That causes issues with migration files. As it is not possible to reference right url in the migration files.

Here are two more issues related to this that I found:
https://github.com/orgs/supabase/discussions/680
https://github.com/orgs/supabase/discussions/8197
utkarsh1097 commented 1 month ago

I am also interested in a way to enable post-signup verification. While a custom backend (using supabase.auth.admin on the server side + custom metadata) should help develop an alternative solution, I was wondering whether there can be built-in support for this problem without major changes.

A few observations:

image

With this, I think it would be great to allow devs to configure AllowUnverifiedEmailSignIns from the dashboard, and use its value for email & password-based sign-ins. I believe doing this (along with potentially making slight tweaks in the sign-up API as well) should address the issue.

allenchuang commented 3 days ago
image

Where is this option?