Linking custom auth provider with Firebase
Asked Answered
L

2

11

I read that with Firebase I can allow users to sign in to my app using multiple authentication providers by linking auth provider credentials to an existing user account. Is possible linking custom auth provider such as Linkedin? I read that I need to pass the AuthCredential object to the signed-in user's linkWithCredential method but I don't find a custom AuthCredential.

Liberate answered 21/10, 2016 at 8:20 Comment(0)
E
12

One way to link an unsupported provider custom token to an existing account is to get the Firebase account's user id and the unsupported provider user id and save a hash map that takes in the unsupported provider id and returns the firebase uid which you want to link to. When the user signs in to unsupported provider with custom token, you get the corresponding firebase uid from the map and return a custom token with that uid which on signInWithCustomToken resolves with the original firebase user.

The downside is that you don't see the unsupported provider in the list of provider data within the user. You also need to store the map.

Excellence answered 21/10, 2016 at 18:7 Comment(4)
To make it clear this answer, simply "uid" of token should be the same with current user id. For instance, user logged in as Anonymous with "V5T0SE15mublW3gTr9lr04q7uxG3" user id. Now, you can create new token with uid: "V5T0SE15mublW3gTr9lr04q7uxG3", because you know the current user id. And once you got new token, you can login again: signInWithCustomToken( newToken ). These two users merged.Coolie
@dino this comment alone, i kid you not, has been the only thing on the entire internet to give me the information I needed. I have a normal rest API backend, but my users first create firebase provider based account on client, and use the verified jwt payload for find/create. I was trying to figure out how to use REST auth apis to administer accounts, but i needed to exchange custom token for idtoken. Once I started signing my custom jwt with the firebase id, and signing them in, i now finally can exchange the custom token for idTokenCagliostro
I think the confusion came from there being no way to "link" an existing account to with customToken, so I assumed signing the user back in with my own jwt would cause account duplication, it never even crossed my mind to use the same identifierCagliostro
This helped me greatly and the implementation was actually simpler than I anticipated. I would never expect that I can create a new token using an existing Firebase user id...Abseil
S
7

I would like to expand bojeil's answer.

There is firebaseUser.linkWithCredential(credential) for supported Providers, but not equivalent for customProvider. Linking customProvider must be done by backend (or maybe sth like Firebase Functions). Because link means one of these:

  • add email
  • add phone number
  • custom logic (add user claim)

to the Firebase User object.

Flow is like this:

  1. Client gets email, phone or some unique info from customProvider (Line, LinkedIn, Huawei...) and send them to Backend including firebaseToken.
  2. (Backend may verify those data by asking to customProvider). Then Backend adds those info to FirebaseUser object. (Also backend has to check if those data are already attached to some other user. You might reject linking, since there is another user already with these email, phone...)
  3. Backend saves <CustomProviderId-FirebaseUserId> pair somewhere (e.g: FireStore). This is done because in future, when user wants to sign in using customProvider, backends needs to create CustomToken (so client can call firebaseAuth.signInWithCustomToken) using Firebase Id of that user. So this Mapping is solution for that problem.
  4. Backend will respond with 200 HTTP response code to indicate linking is successful
  5. Client calls firebaseUser.reload() to get newly attached data (email, phone etc...)
  6. If User Claims are updated in step-2, then client also has to call firebaseUser.getIdToken(force=true) to get the updated user claims.

There are challenges:

  • If customProvider only gives email, you need to check if that email is attached to any other user already.
  • If customProvider only gives phone, you need to check if that phone is attached to any other user already.
  • If customProvider can give both email and phone, complexity increases, as you have to check if any of those already attached to any other user.
  • If customProvider does not provide email or phone, then you need unique info for that user for that custom provider (such as Huawei User Id).
  • CustomProvider will not be in firebaseUser.providerData list, so you might add user claims. (e.g. {kakaoTalk:true, huawei:true}). Depending on case, you don't need that. For example, if customProvider is WhatsApp, then if phone exists in firebaseUser.phoneNumber it means WhatsApp is linked (even phone is added using another sign in provider).
  • If you allow Anonymous users, then linking customProvider may not update firebaseUser.isAnonymous on client if email/phone is not updated, client will still see firebaseUser as anonymous. One solution is to check if linkedProviders are empty to consider user as anonymous, if that is ok with your business logic. Other solution is Anonymous user status changes when you sign in user using signInWithCustomToken. So after linking customProvider is successful, silently logout and sign in with customToken so user becomes not anonymous.
  • If you link customProvider with email to anonymous user, that user's email field is updated. This will force client to logout and throw FirebaseAuthInvalidUserException with errorCode ERROR_USER_TOKEN_EXPIRED. User has to sign in again.
Solley answered 14/3, 2021 at 15:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.