supabase / auth-js

An isomorphic Javascript library for Supabase Auth.
MIT License
321 stars 152 forks source link

feat: add identity linking methods #814

Closed kangmingtay closed 6 months ago

kangmingtay commented 7 months ago

What kind of change does this PR introduce?

TODO

github-actions[bot] commented 6 months ago

:tada: This PR is included in version 2.60.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

chhuang commented 5 months ago

I think I've found a few issues with this, specifically using twitter as the provider.

/account?error=server_error&error_code=500&error_description=Request+token+doesn%27t+match+token+in+callback#error=server_error&error_code=500&error_description=Request+token+doesn%2527t+match+token+in+callback

@kangmingtay @J0 would you be able to help please?

J0 commented 5 months ago

Hey @chhuang,

Thanks for filing the issue and for your patience with us while we work through the tickets. Might need to trouble you for a bit of information. For:

After doing unlinkIdentity for twitter, I can still sign back in with the same Twitter account and it gets added/linked back to the same old account automatically. The Twitter account is using a different email address, I'd assume if I unlink it, and then do a new sign in/sign up, it would create a new account for me based on the email from the Twitter account, but that is not the case.

As I understand the first steps would be:

  1. User signs in with Google OAuth (john@gmail.com) and then signs in with Twitter OAuth (primary_email: john@gmail.com). Let's call this UserA.
  2. Developer calls unlinkIdentity for twitter . UserA now has one identity.

Mind sharing more about the next step?

I can still sign back in with the same Twitter account and it gets added/linked back to the same old account automatically.

I am guessing here but would it be:

If you have a linked video that would be very helpful

I'm not sure if this is related, unlinkIdentity remove the record from the auth.identities table but it doesn't clean/delete the data in raw_user_meta_data in the auth.users table (which is where the twitter data is stored).

I think unlinkIdentity only updates the providers app_meta_data and does not touch raw_user_metadata. Do you mind sharing what fields remain in raw_user_metadata and what you'd like cleared?

linkIdentity using twitter as the provider doesn't work as expected. It returns error code 500 not found and request token doesn't match token in callback. It works fine for google and discord as the provider. It also works fine when I use with signInWithOAuth, so this should not be a Twitter APP settings issue on my end. I can see the error in the URL after the redirect back from Twitter. Apart from the error, it also logs me out of the application.

I'm spitballing and will need to check further but there might be a mismatch in the one of the fields of the JWT. If you see any differences that stand out let us know.

Thanks!

chhuang commented 5 months ago

Thanks for looking into this @J0

Scenario 1 A (not working):

  1. User A signs in with Google (user-a-google@gmail.com)
  2. User A links Twitter (user-a-twitter@gmail.com), the linking fails. Important to note that this is a brand new Twitter account that it has never been used to create or sign in before in our system.
  3. User A is redirected back and logged out automatically: {"code":401,"msg":"invalid claim: missing sub claim"}

image

In the same scenario, User A can sign in with Twitter (user-a-twitter@gmail.com) with no problem. I only did this after I failed to link it to user-a-google@gmail.com in step 1. But now I have created 2 different accounts, one with Google and one with Twitter. Obviously this was not the initial intention.

Scenario 1 B (working):

  1. User A signs in with Google (user-a-google@gmail.com)
  2. User A links Discord (user-a-discord@gmail.com)
  3. User A is redirected back and Discord is added and linked to the same account.

Scenario 2:

  1. User A signs in with Google (user-a-google@gmail.com)
  2. User A adds/links Twitter to the account (different email, user-a-twitter@gmail.com)
  3. User A signs out
  4. User B signs in with Google (user-b-google@gmail.com)
  5. User B adds/links Twitter (user-a-twitter@gmail.com), the linking fails because email is already used and linked to User A
  6. User B is redirected back to the site and logged out automatically

I think the UX can be improved for step 6? I can see this is in the TODO of this PR and it's checked, can you confirm it's working as intended please?

image

Scenario 3:

  1. User A signs in with Twitter (user-a-twitter@gmail.com)
  2. User A links Discord to the account (different email, user-a-discord@gmail.com)
  3. User A tries to unlink Twitter, the unlink fails: {"code":403,"msg":"Unable to unlink identity due to email conflict"}

Unlike the other scenarios, here the user is not logged out automatically. I can also unlink my Discord without problem.

What is the reason I can't unlink my Twitter here? Since I've also added Discord, I should be able to unlink Twitter right?

image

kangmingtay commented 5 months ago

Hi @chhuang, thanks for providing all these details.

Scenario 1 will be fixed by this PR.

Scenario 2 is expected but you should not be logged out in step 6 - i'll look into why that's happening in the client library

Scenario 3 happens because you already have another user / identity in your db that uses the email user-a-discord@gmail.com. When you unlink the twitter identity from the user, we need to update the auth.users.email column which has a unique constraint on it. If there is another user that initially signed in with discord using user-a-discord@gmail.com, this email will already be used in the auth.users table. This is a known issue and we're working on relaxing the email constraint on oauth identities so that this error goes away.

chhuang commented 5 months ago

Hi @chhuang, thanks for providing all these details.

Scenario 1 will be fixed by this PR.

Scenario 2 is expected but you should not be logged out in step 6 - i'll look into why that's happening in the client library

Scenario 3 happens because you already have another user / identity in your db that uses the email user-a-discord@gmail.com. When you unlink the twitter identity from the user, we need to update the auth.users.email column which has a unique constraint on it. If there is another user that initially signed in with discord using user-a-discord@gmail.com, this email will already be used in the auth.users table. This is a known issue and we're working on relaxing the email constraint on oauth identities so that this error goes away.

Thanks @kangmingtay for the fix!

Can you tell me how to get the fix? Which library should I update?