supabase / auth

A JWT based API for managing users and issuing JWT tokens
https://supabase.com/docs/guides/auth
MIT License
1.3k stars 326 forks source link

Anonymous user identity not linking #1525

Open muezz opened 3 months ago

muezz commented 3 months ago

Describe the bug If I sign in using Google, re-install the app, open it (which automatically signs the user in anonymously) and then try to link identity using the Google provider, I get an error.

To Reproduce Steps to reproduce the behavior:

  1. Create a fresh Flutter project and add supabase_flutter as a dependancy.
  2. Run the project and set up a button to performt he following action:
    await Supabase.instance.client.auth.signInWithOAuth(
    OAuthProvider.google,
    redirectTo: 'com.my_app://login-callback/',
    authScreenLaunchMode: LaunchMode.externalApplication,
    );
  3. After signing up successfully, uninstall the app from the simulator.
  4. Add the following code before runApp():
    if (Supabase.instance.client.auth.currentSession == null) {
    await Supabase.instance.client.auth.signInAnonymously();
    }
  5. Update the onTap callback on the previous button to trigger the following code:
    await Supabase.instance.client.auth.linkIdentity(
    OAuthProvider.google,
    redirectTo: 'com.my_app://login-callback/',
    authScreenLaunchMode: LaunchMode.externalApplication,
    );
  6. You will be able to sign in with google successfully but as soon as you get back to the app, you will get this error: AuthException(message: Identity is already linked to another user, statusCode: null)

Expected behavior The anonymous user ID (created on the second app run at step 4) should get merged with the already existing user ID from step 2.

Version: ├── supabase_flutter 2.5.0 │ ├── supabase 2.1.0 │ │ ├── functions_client 2.0.0 │ │ ├── gotrue 2.6.0 │ │ ├── postgrest 2.1.1 │ │ ├── realtime_client 2.0.3 │ │ ├── storage_client 2.0.1

Additional context This also brings up a question about what would happen to the data created by the anonymous user? Ideally, I would expect that data to be "moved" to the previously existing user.

dshukertjr commented 3 months ago

I'm going to transfer this issue to our Auth server repo to discuss further.

muezz commented 2 months ago

@dshukertjr any update on this issue?

dshukertjr commented 2 months ago

@muezz Actually, I was reading through the issue again, and the behavior you outlined is the expected behavior.

You simply cannot have two auth users to be tied to a single Google OAuth account, and that is what the error message is saying. When you get the Identity is already linked to another user error message, what you can do is to just perform the regular Google sign-in using either signInWithIdToken or the signInWithOAuth. Once the sign-in is complete, the user will be brought back to the original account. Note that when this happens, the activities from the second anonymous account will be lost, so you are going to have to set something up manually if you want to persist those data.

hala94 commented 3 weeks ago

@dshukertjr

Maybe I misunderstood something, but this breaks the flow. ( repeated login gets weird double redirect UX )

Existing user can always log out and another "anonymous" user be created on the same device, probably automatically for most use cases. This means that when they try to "sign in" again -> we have an option to call either linkIdentity or signInWithOAuth -> but we cannot know which one to call, the current session user is anonymous again.

(I'm using Next.js, server side flows)

dshukertjr commented 2 weeks ago

Fair enough. Passing the feedback to the auth team.

Let me just re-open this issue.

silentworks commented 2 weeks ago

@hala94 I think what @dshukertjr stated is correct and a fine way of going about it. The only change I would make to his recommendation is that after the Identity is already linked to another user message is given to a user, they should be given a sign in button to perform the signInWithOAuth. The reason why it would be bad for linkIdentity to perform the signInWithOAuth internally is that if a user was signed in already via email/password lets say and they now decide they want to linkIdentity to a OAuth provider and it turns out that the OAuth they are trying to link is already linked to another account, they would get signed out of their current session (email/password session) and then signed back into the OAuth session instead which is a completely different account all together. I think with the current implementation, it allows the developer to chose the flow they want to provide for the user of their app.

NB: I'm not a Supabase employee, just to be clear that this is my personal take on this matter.

sapphire008 commented 1 week ago

Related to this, when linking the user via email, updateUser works when updating email, but throws AuthException(message: Anonymous user cannot update password) when also specifying a password. It would be nice to allow them to sign up with email and update their password.