Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking custom auth provider with Firebase

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.

like image 649
mary Avatar asked Oct 21 '16 08:10

mary


Video Answer


2 Answers

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.

like image 113
bojeil Avatar answered Oct 06 '22 00:10

bojeil


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.
like image 27
Jemshit Iskenderov Avatar answered Oct 06 '22 00:10

Jemshit Iskenderov