You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I can sign in via facebook and it will not create another account because it is already connected to a user even though they different email address returned during OAuth
I can sign in via twitter and it will not create another account because it is already connected to a user even though twitter has no email address returned during OAuth
Things also that we can keep in mind that..
If a user signed up with email/password with an email of test@gmail.com, user can still create an separate account via facebook/twitter if this social has the same email.
Unless link or merge, then it will create new account.
You can only link account if there is a user that is currently logged in on app/system to determine where would you append the additional data
Reacted by Manoj Chandrashekar, Ammar Faris, Antoine Frankart, Jose Albizures, Rafael Arazola, Sindre, David Tai, Brian D , MetalMonkey, Sebastien Dubois and 2 more
user logs in with Facebook OAuth and their facebook account has the email 'test@email.com'
Both of these will return the same user uuid.
Is that what you're looking for?
Hi @kiwicopple, thanks for all your teams great work in supabase, lovin' it!
Just want to mention that it would be great if we can link different provider to same account even if the email is different.
Sometimes user use different email for different providers.
And also able to unlink will be great if user want to have separated accounts event the email is the same.
Thanks :)
For anyone wanting to support this, you'd need to propose to https://github.com/netlify/gotrue as that is where the logic behind users and providers live. I don't know if Supabase runs a fork of it, but this is where the request should be going to
Adding another use case here, besides multiple auth paths:
I want to store connections to 3rd party apps, e.g. a Twitter connection for retrieving a user's tweets. Else, I need to duplicate a lot of the OAuth logic and store it separately.
Reacted by David Tai, Philipp Steinrötter, David Furlong and Sebastien Dubois
Reacted by David Tai, Philipp Steinrötter, Badreddine Lejmi and James Thesken
Hi everyone, we currently don't have plans to support manual linking of accounts in the near future. Currently, gotrue only supports automatic linking of accounts based on the user's email.
This could be done theoretically with a procedure and policies that updates the auth.users and auth.identities tables.
You would basically delete the identity id in auth.identities, remove the provider in auth.users.raw_app_meta_data and auth.users.raw_user_meta_data.
Adding it would require logging out and back in with the provider assuming the email is the same. If you wanted to take that a step further, you could create another procedure with an http function that runs the full oAuth 2 protocol, then saves it manually. You could also theoretically add the missing option for signin with popup.
Of course, if someone does either of these two options, please share the code here.
Hey everyone, we're aware of the need to customize the account linking logic and have some plans to make it happen via web hooks / triggers. However, this is not something we're going to be working on in the short term.
I'll be closing this issue as account linking is supported if the user has the same email in the social login providers.
Reacted by Stephen Daoud, Chief Yeti, Angelo RC, Allen Shen, Albert Bethlowsky Hammerich and Aleksandr Zhukov
I don't get the point of closing this and stating that account linking is suppoerted when its the same email but the point of this whole thread is to get support for when its NOT THE SAME EMAIL. Its a must have future in auth now and days. This should really be pushed up the priority list.
Reacted by Stephen Daoud, jojobii, Badreddine Lejmi, Julian Carrier, Chief Yeti, Arman R. Tav, mhddngs, ericola, Allen Shen, Smokey and 2 more
We are working on it! Sorry for the delay... it's not a simple feat as we need to make sure not to break any existing behavior, while allowing for an API that we won't have to go back to in 5 months time.
@hf Thanks for the update, that's awesome!! ✨ any rough ETA?
We'll need some time to roll this feature out to all projects on Supabase but if you are self-hosting, you should be able to use this new feature with the latest version of gotrue. The target ETA for getting this out to all projects is by LWX
The corresponding client library bindings will also be added to the js library in this PR: supabase/auth-js#814
The process for linking / unlinking an identity will look something like this:
// assume user is already logged in and authenticated// link the current user to a google identity// this works very similar to signInWithOAuth() and will redirect the user to google to complete the oauth flow // once the oauth flow has been completed, the user will be redirected back to the app with the identity linkedconst{ data, error }=awaitsupabase.auth.linkIdentity({provider: 'google'})// fetch all identities linked to the current userconst{data: { identities }}=awaitsupabase.auth.getUserIdentities()constgoogleIdentity=identities.find(identity=>identity.provider==='google')// unlink an identityawaitsupabase.auth.unlinkIdentity(googleIdentity)
Reacted by Matt Ketmo, H. Kamran, Arman R. Tav, Angelo RC, Kabo, Mateusz Wos, John D. Pope, Brand Besties app@brandbesties.com, Moe Amaya and diogo-logrado-unp
@kangmingtay I'm migrating from Firebase Auth to Supabase Auth now that there is anonymous account support. I'm on react-native but the docs for linking seem to assume web. What is the correct auth API to use to link an anonymous account to a credential retrieved from a native social auth provider?
For example the docs suggest using supabase.auth.linkIdentity({ provider: 'google' }) stating that "the user will be redirected to Google to complete the OAuth2.0 flow" which probably won't work on react native, it seems to be assuming web. Some of the provider documentation like google auth demonstrate signing in using a token fetched from the native auth flow (react-native-google-sign-in) using supabase.auth.signInWithIdToken but there is no mention of linking the credential to an anonymous account.
The workflow I'm trying to replicate from Firebase auth is that new users always get an anonymous account and at some later point in time are prompted to link a real credential so they don't lose their progress. It seems like maybe the supabase client is missing a linkIdentityWithIdToken method?
@kangmingtay I'm migrating from Firebase Auth to Supabase Auth now that there is anonymous account support. I'm on react-native but the docs for linking seem to assume web. What is the correct auth API to use to link an anonymous account to a credential retrieved from a native social auth provider?
For example the docs suggest using supabase.auth.linkIdentity({ provider: 'google' }) stating that "the user will be redirected to Google to complete the OAuth2.0 flow" which probably won't work on react native, it seems to be assuming web. Some of the provider documentation like google auth demonstrate signing in using a token fetched from the native auth flow (react-native-google-sign-in) using supabase.auth.signInWithIdToken but there is no mention of linking the credential to an anonymous account.
The workflow I'm trying to replicate from Firebase auth is that new users always get an anonymous account and at some later point in time are prompted to link a real credential so they don't lose their progress. It seems like maybe the supabase client is missing a linkIdentityWithIdToken method?
I'm in the same boat, and managed to get it to work using linkIdentity, however I'm using expo-web-browser and expo-auth-session in my app to achieve this.
I feel like there's a bit of wonkiness to this though. If the anonymous user attempts to link to a google (or apple account) with one that is already used.. it seems to fail silently, and I'm not able to display any meaningful message to the client app.
Edit: Just found the fix for my problem above, had to read the url from the Linking.addEventListener event.. My bad!
Thanks for implementing account linking! :) Referring to @evelant message and #1645 issue, I think it would be helpful to add support for linking accounts via id token. If someone has implemented mobile native login, they are currently forced to start the linking process in a web view. While this isn’t a major issue, native login offers a better user experience, and I’m sure many developers would prefer to keep things consistent in their apps. After looking at the code, it seems like linking accounts via an id token shouldn’t be too difficult, but it would be great if one of the maintainers could share their thoughts on whether this is a good approach or what the plans are for improving account linking.
Bumping a request for a linkIdentityWithIdToken function or similar functionality 👍
This would perform the following action:
Take the existing (possibly anonymous) user
Link the provider to the existing user using an OIDC ID token for that provider
My use case for this feature:
Currently I have an Apple OIDC ID token acquired using expo-apple-authentication
There's no way to link the Apple provider to the previously created anonymous user using this OIDC ID
Attempted alternatives:
Using linkIdentity is not great since this requires the use of a WebView in the app instead of using the native auth implementation provided by expo-apple-authentication
signInWithIdToken creates an entirely new user, even if you're already signed in as an (anonymous) user, which is undesired for my use case
Reacted by LÊ VĨNH NHÂN ĐỨC, martyfuhry and Aleksandr Zhukov
We are working on it! Sorry for the delay... it's not a simple feat as we need to make sure not to break any existing behavior, while allowing for an API that we won't have to go back to in 5 months time.
Would you please let us know the status of this or review and merge #1885? Trying to work around this is painful.
Actually this appears to be a blocker for passing App Store review. Since we offer users the choice of using an anonymous account and then signing up later the inability to link with a token triggers an app store review failure. Apple will not accept supabase auth's default workflow of opening the default web browser to perform auth. They require use of the native sdk. This is not a problem for new signups because we can use expo-apple-authentication and create a new account with the token. This is a blocker to app store acceptance if using anonymous accounts. Right now there is no way to link an anonymous account to a token without using the web based oauth flow which apple will not accept through review.
For others waiting for gotrue to support linking to tokens, I realized once again that one of the great things about supabase is "it's just postgres". You can manually verify a token and insert an identity to link a token to an account in an edge function or similar server function. Here's how I'm doing it (contains some stuff specific to my app because I use effect-ts rpc on bun on fly.io to avoid the Deno woes of edge-functions but should be enough to go on). I looked at what gotrue was doing and the auth schema and figured out what data I needed to insert. Works like a charm!
import{createHash}from"crypto"import{Effect}from"effect"import*asjosefrom"jose"import{RpcLinkAnonymousWithApple}from"myapp/schemas/RPCSchema"import{AuthTokenValidationError,InvalidArgsError}from"myapp/utils/errors"import{Session}from"../../index"import{runEffectWithTransaction,runSql}from"../dbEffect"interfaceApplePublicKey{kty: stringkid: stringuse: stringalg: stringn: stringe: string}interfaceApplePublicKeyResponse{keys: ApplePublicKey[]}interfaceAppleIDTokenPayload{iss: stringsub: stringaud: stringiat: numberexp: numberemail?: stringemail_verified?: booleanis_private_email?: booleanauth_time?: numbernonce?: stringname?: string}functioncreateIdentityData(payload: AppleIDTokenPayload){// Ensure we match GoTrue's expected structureconstidentityData={sub: payload.sub,iss: payload.iss,aud: Array.isArray(payload.aud) ? (payload.audasstring[]) : [payload.aud],iat: payload.iat,exp: payload.exp,email: payload.email??null,email_verified: payload.email_verified??false,is_private_email: payload.is_private_email??null,auth_time: payload.auth_time??null,provider: "apple",provider_id: payload.sub,name: payload.name??null,full_name: payload.name??null,avatar_url: null}asconst// Validate required fieldsif(!identityData.sub)thrownewError("Missing sub claim")if(!identityData.iss)thrownewError("Missing iss claim")if(!identityData.aud)thrownewError("Missing aud claim")returnidentityData}constsha256=(str: string)=>{returncreateHash("sha256").update(str).digest("hex")}exportconstlinkAnonymousWithApple_V0=({ idToken, nonce }: RpcLinkAnonymousWithApple)=>Effect.gen(function*(_){// Get the anonymous user's ID from the auth tokenconstsession=yield*_(Session)constanonymousUserId=session.uid// 1. Fetch Apple's public keysconstappleKeysResponse=yield*_(Effect.tryPromise({try: ()=>fetch("https://appleid.apple.com/auth/keys"),catch: error=>newInvalidArgsError({cause: error})}))constappleKeys: ApplePublicKeyResponse=yield*_(Effect.tryPromise({try: ()=>appleKeysResponse.json(),catch: error=>newInvalidArgsError({cause: error})}))// 2. Decode the JWT header to get the key ID (kid)constdecodedHeader=jose.decodeProtectedHeader(idToken)constmatchingKey=appleKeys.keys.find(k=>k.kid===decodedHeader.kid)if(!matchingKey){returnyield*_(Effect.fail(newInvalidArgsError({msg: "No matching key found for token"})))}// 3. Convert Apple's JWK to PEM format and verify the tokenconstpublicKey=yield*_(Effect.tryPromise({try: ()=>jose.importJWK(matchingKey),catch: error=>newInvalidArgsError({cause: error})}))// 4. Verify the tokenconstverifyOptions: jose.JWTVerifyOptions={issuer: "https://appleid.apple.com",algorithms: ["RS256"],audience: "your.client.id.here",maxTokenAge: "6m",
...(nonce&&{nonce: sha256(nonce)})}constverified=yield*_(Effect.tryPromise({try: ()=>jose.jwtVerify(idToken,publicKey,verifyOptions),catch: error=>newAuthTokenValidationError({cause: error})}))if(!verified||!verified.payload.sub){returnyield*_(Effect.fail(newInvalidArgsError({msg: "Invalid token"})))}// 5. Start transaction to link accountsconstidentityResult=yield*_(runSql("linkAnonymousWithApple",sql=>{constappleId=verified.payload.sub!constidentityDataJson=createIdentityData(verified.payloadasAppleIDTokenPayload)returnsql` WITH user_check AS ( SELECT id, is_anonymous FROM auth.users WHERE id = ${anonymousUserId}::uuid AND is_anonymous = true FOR UPDATE ) INSERT INTO auth.identities ( provider_id, user_id, identity_data, provider, last_sign_in_at, created_at, updated_at ) SELECT ${appleId}::text,${anonymousUserId}::uuid,${identityDataJsonasany}::jsonb, 'apple'::text, NOW(), NOW(), NOW() FROM user_check WHERE is_anonymous = true RETURNING id; `asany}))// 6. Update user's anonymous status and metadataconstuserResult=yield*_(runSql("updateUserAfterAppleLinking",sql=>{constemail=typeofverified.payload.email==="string" ? verified.payload.email : ""constemailConfirmedAt=verified.payload.email_verified ? newDate() : nullreturnsql` UPDATE auth.users SET is_anonymous = false, email = NULLIF(${email}::text, '')::text, email_confirmed_at = COALESCE(${emailConfirmedAt}, NULL)::timestamptz, updated_at = NOW() WHERE id = ${anonymousUserId}::uuid AND is_anonymous = true RETURNING id; `asany}))return{success: true}}).pipe(runEffectWithTransaction)
Reacted by John D. Pope, Jonathan Mieloo and Aleksandr Zhukov
@kangmingtay
We really need a linkIdentityWithIdToken for linking google/apple account with anonymous user via ID token.
Current linkIdentity witch use browser way is very inconvenient for mobile apps. signInWith(IDToken) already allows native sign in for mobile apps.
JFYI: in our project we decided to remove sing-in functionality, because browser way is not suitable for us. Waiting for linkIdentityWithIdToken support.
This issue has been open for nearly 5 years. It seems it got partially implemented but there are a lot of outstanding issues and missing cases, especially linkIdentityWithIdToken.
This is a real pain point, especially for those of us with react native apps. If you use supabase and want to offer social auth in a react native app you will be rejected by Apple app store review if you try to use the documented method. You must implement a totally custom solution like I outlined above to pass review.
IMO it should at least be documented that "Social auth is not supported on react-native iOS via supabase-js. If you need social auth on react-native iOS you must implement token handling and auth insert manually on your backend".
@kangmingtay any chance this can finally get some attention to fill out the edge cases, improve the docs, and resolve the rough edges mentioned in supabase/auth-js#814 so that auth can finally work well on all platforms?
Activity
rodjoseph commentedon Jul 27, 2021
I think this would be great as well
kiwicopple commentedon Jul 28, 2021
Hey @sandbox-apps - this is technically possible, as long as the user has the same email for all accounts (since this is the primary login mechanism).
For example
Both of these will return the same user
uuid.Is that what you're looking for?
sandbox-apps commentedon Aug 17, 2021
Firebase has this setup where
Example:
Another example:
Result:
Things also that we can keep in mind that..
sandbox-apps commentedon Aug 17, 2021
Further more you can unlink provider via providerId with the currentUser
eMeRiKa13 commentedon Nov 4, 2021
I would love to have the workflow you describe @sandbox-apps!
It seems the "perfect" way to manage auth with 3rd party providers.
didavid61202 commentedon Dec 6, 2021
Hi @kiwicopple, thanks for all your teams great work in supabase, lovin' it!
Just want to mention that it would be great if we can link different provider to same account even if the email is different.
Sometimes user use different email for different providers.
And also able to unlink will be great if user want to have separated accounts event the email is the same.
Thanks :)
firatoezcan commentedon Dec 16, 2021
For anyone wanting to support this, you'd need to propose to https://github.com/netlify/gotrue as that is where the logic behind users and providers live. I don't know if Supabase runs a fork of it, but this is where the request should be going to
henningko commentedon May 10, 2022
Adding another use case here, besides multiple auth paths:
I want to store connections to 3rd party apps, e.g. a Twitter connection for retrieving a user's tweets. Else, I need to duplicate a lot of the OAuth logic and store it separately.
diogoribeirodev commentedon Aug 14, 2022
Any updates on this
kangmingtay commentedon Sep 14, 2022
Hi everyone, we currently don't have plans to support manual linking of accounts in the near future. Currently, gotrue only supports automatic linking of accounts based on the user's email.
jdgamble555 commentedon Sep 28, 2022
This could be done theoretically with a procedure and policies that updates the
auth.usersandauth.identitiestables.auth.identities, remove the provider inauth.users.raw_app_meta_dataandauth.users.raw_user_meta_data.Adding it would require logging out and back in with the provider assuming the email is the same. If you wanted to take that a step further, you could create another procedure with an http function that runs the full oAuth 2 protocol, then saves it manually. You could also theoretically add the missing option for signin with popup.
Of course, if someone does either of these two options, please share the code here.
J
hf commentedon Sep 29, 2022
Hey everyone, we're aware of the need to customize the account linking logic and have some plans to make it happen via web hooks / triggers. However, this is not something we're going to be working on in the short term.
I'll be closing this issue as account linking is supported if the user has the same email in the social login providers.
rlee1990 commentedon Feb 11, 2023
I don't get the point of closing this and stating that account linking is suppoerted when its the same email but the point of this whole thread is to get support for when its NOT THE SAME EMAIL. Its a must have future in auth now and days. This should really be pushed up the priority list.
16 remaining items
aaroniker commentedon Nov 19, 2023
@hf Thanks for the update, that's awesome!! ✨ any rough ETA?
kangmingtay commentedon Dec 1, 2023
Hey everyone, just an update, we've merged in 2 PRs that will make manual linking possible very soon:
We'll need some time to roll this feature out to all projects on Supabase but if you are self-hosting, you should be able to use this new feature with the latest version of gotrue. The target ETA for getting this out to all projects is by LWX
The corresponding client library bindings will also be added to the js library in this PR: supabase/auth-js#814
The process for linking / unlinking an identity will look something like this:
ARMATAV commentedon Dec 2, 2023
evelant commentedon May 21, 2024
@kangmingtay I'm migrating from Firebase Auth to Supabase Auth now that there is anonymous account support. I'm on react-native but the docs for linking seem to assume web. What is the correct auth API to use to link an anonymous account to a credential retrieved from a native social auth provider?
For example the docs suggest using
supabase.auth.linkIdentity({ provider: 'google' })stating that"the user will be redirected to Google to complete the OAuth2.0 flow"which probably won't work on react native, it seems to be assuming web. Some of the provider documentation like google auth demonstrate signing in using a token fetched from the native auth flow (react-native-google-sign-in) usingsupabase.auth.signInWithIdTokenbut there is no mention of linking the credential to an anonymous account.The workflow I'm trying to replicate from Firebase auth is that new users always get an anonymous account and at some later point in time are prompted to link a real credential so they don't lose their progress. It seems like maybe the supabase client is missing a
linkIdentityWithIdTokenmethod?f-bog commentedon Jul 2, 2024
I'm in the same boat, and managed to get it to work using linkIdentity, however I'm using
expo-web-browserandexpo-auth-sessionin my app to achieve this.I feel like there's a bit of wonkiness to this though. If the anonymous user attempts to link to a google (or apple account) with one that is already used.. it seems to fail silently, and I'm not able to display any meaningful message to the client app.
Edit: Just found the fix for my problem above, had to read the url from the Linking.addEventListener event.. My bad!
lawinski commentedon Sep 1, 2024
Thanks for implementing account linking! :) Referring to @evelant message and #1645 issue, I think it would be helpful to add support for linking accounts via id token. If someone has implemented mobile native login, they are currently forced to start the linking process in a web view. While this isn’t a major issue, native login offers a better user experience, and I’m sure many developers would prefer to keep things consistent in their apps. After looking at the code, it seems like linking accounts via an id token shouldn’t be too difficult, but it would be great if one of the maintainers could share their thoughts on whether this is a good approach or what the plans are for improving account linking.
jonathanlab commentedon Sep 10, 2024
Bumping a request for a
linkIdentityWithIdTokenfunction or similar functionality 👍This would perform the following action:
My use case for this feature:
expo-apple-authenticationAttempted alternatives:
linkIdentityis not great since this requires the use of a WebView in the app instead of using the native auth implementation provided byexpo-apple-authenticationsignInWithIdTokencreates an entirely new user, even if you're already signed in as an (anonymous) user, which is undesired for my use caselvxduck commentedon Sep 21, 2024
I am facing the same issue.
I Hope Supabase team will add native Google and Apple sign-in to the
linkIdentitysoon.johndpope commentedon Dec 23, 2024
@jonathanlab - drafted linkIdentityWithIdToken - #1885
evelant commentedon Jan 15, 2025
@hf @kangmingtay 14 months ago:
Would you please let us know the status of this or review and merge #1885? Trying to work around this is painful.
evelant commentedon Jan 15, 2025
Actually this appears to be a blocker for passing App Store review. Since we offer users the choice of using an anonymous account and then signing up later the inability to link with a token triggers an app store review failure. Apple will not accept supabase auth's default workflow of opening the default web browser to perform auth. They require use of the native sdk. This is not a problem for new signups because we can use expo-apple-authentication and create a new account with the token. This is a blocker to app store acceptance if using anonymous accounts. Right now there is no way to link an anonymous account to a token without using the web based oauth flow which apple will not accept through review.
evelant commentedon Jan 20, 2025
For others waiting for gotrue to support linking to tokens, I realized once again that one of the great things about supabase is "it's just postgres". You can manually verify a token and insert an identity to link a token to an account in an edge function or similar server function. Here's how I'm doing it (contains some stuff specific to my app because I use effect-ts rpc on bun on fly.io to avoid the Deno woes of edge-functions but should be enough to go on). I looked at what gotrue was doing and the auth schema and figured out what data I needed to insert. Works like a charm!
XanderZhu commentedon May 8, 2025
@kangmingtay
We really need a
linkIdentityWithIdTokenfor linking google/apple account with anonymous user via ID token.Current
linkIdentitywitch use browser way is very inconvenient for mobile apps.signInWith(IDToken)already allows native sign in for mobile apps.JFYI: in our project we decided to remove sing-in functionality, because browser way is not suitable for us. Waiting for
linkIdentityWithIdTokensupport.johndpope commentedon May 8, 2025
PR + Code is here - (previous or got blown away using github ) #2002
evelant commentedon Jun 25, 2026
This issue has been open for nearly 5 years. It seems it got partially implemented but there are a lot of outstanding issues and missing cases, especially linkIdentityWithIdToken.
This is a real pain point, especially for those of us with react native apps. If you use supabase and want to offer social auth in a react native app you will be rejected by Apple app store review if you try to use the documented method. You must implement a totally custom solution like I outlined above to pass review.
IMO it should at least be documented that "Social auth is not supported on react-native iOS via supabase-js. If you need social auth on react-native iOS you must implement token handling and auth insert manually on your backend".
@kangmingtay any chance this can finally get some attention to fill out the edge cases, improve the docs, and resolve the rough edges mentioned in supabase/auth-js#814 so that auth can finally work well on all platforms?