firebase / FirebaseUI-iOS

iOS UI bindings for Firebase.
Apache License 2.0
1.51k stars 476 forks source link

Multiple Facebook apps for one Firebase project #427

Open AndriyGo opened 6 years ago

AndriyGo commented 6 years ago

We have 5 apps which we would like to integrate with Firebase in one project. Each of them is associated with a separate Facebook app for marketing purposes. However, we want our users' data to be stored in one place. I know that I cannot set more than 1 Facebook app ID in the Firebase console.

However, by browsing through the Firebase UI implementation of the Facebook login it seems to me that kFacebookAppId is read from the Info.plist file. We do have these IDs set for all our apps. My question is whether this out of the box solution would work in our case? Or will there be an error because we are using several Facebook apps to login users into one Firebase project?

morganchen12 commented 6 years ago

You'll most likely run into errors, though I'm not sure which errors.

@protocol86 can explain more.

AndriyGo commented 6 years ago

@morganchen12 thank you for your reply. I am looking forward to hearing more about this potential use case.

I know that we could use custom authentication with Facebook and pass the token to Firebase. The problem, however, is that current Firebase UI does not seem to support custom authentication methods/logic. So, if we follow this route, we need to redesign UI and logic for all authentication methods, not just Facebook, which seems like an overkill.

Given this and the fact that our use case scenario seems pretty reasonable, I am willing to stick to using Firebase UI. And we could either use the current version (in case it is compatible with multiple Facebook apps) or submit a PR which makes it possible.

protocol86 commented 6 years ago

@AndriyGo ,

Unfortunately this use-case is not currently supported and adding support would be non-trivial (a PR on your end wouldn't be enough to add support). Note that the FirebaseUI libraries are wrappers above the core Firebase libraries and as a result are subject to the same limitations.

Your original idea of using Custom Auth would be the way to achieve multiple FB apps on the same Firebase project.

Cheers, -Z

AndriyGo commented 6 years ago

@protocol86 thanks for your response. I had several ideas related to a PR which all seem better than rewriting all sign in methods and UI because of our particular Facebook need.

In my opinion, the simplest way to achieve what I want is to define FUICustomAuth class which users could subclass. It would conform to the FUIAuthProvider protocol. And hence it would be possible to add custom sign in logic to it whilst maintaining the logic of all other authentication providers.

What do you think about such approach? Is this something you would be happy to review? If so, would you prefer this new class to be written in Swift?

morganchen12 commented 6 years ago

FirebaseUI-iOS has to be written in ObjC because of its dependency structure, but I'd be happy to review a feature like that.

Essentially what you're proposing is adding custom auth support to FirebaseUI, which seems like a good approach. @protocol86 let us know what you think.

bojeil-google commented 6 years ago

Hey @AndriyGo, adding support for custom authentication (along with existing providers) to FirebaseUI is a feature we'd like to support for all 3 platforms (iOS, Android and web). However, we have a lot of flows that could be affected by this. For example, we are adding anonymous user upgrade flows and have plans for supporting reauthentication flows, etc. We'd need to make sure this is designed correctly so it is compatible with these features and we'd like to aim for feature parity on the 3 platforms.

AndriyGo commented 6 years ago

@bojeil-google I'd be able to submit PRs for Android and iOS fairly soon. As for the web, none of the guys in my company worked with it yet, so it might take more time.

Regarding the architecture and additional flows, I think that the best way to ensure that everything is working is to add extra requirements to the FUIAuthProvider protocol. As I understand, in order to support anonymous user upgrade the authentication provider needs to obtain credentials and then link those with existing anonymous account. As long as this logic is implemented through protocol requirements it should be easy to add it to the custom authentication provider.

What do you think?

AndriyGo commented 6 years ago

Actually, it looks as if I was wrong. The current implementation of Firebase UI does allow the addition of custom authentication providers because FUIAuthProvider protocol is exposed. So, I can easily declare a class which conforms to this protocol and then pass it as one of the authentication providers. So, it looks like no additional PRs are needed. I assume that this holds true for Android and Web as well.

I am going to follow this route and in case I encounter some obstacles I will let you know

AndriyGo commented 6 years ago

@morganchen12 I am going to reopen this issue because the amount of work required to support Facebook login using custom authentication seems like an overkill. From what I was able to learn, the following line of code does some magic and constructs the credentials necessary for Firebase in the standard implementation of Facebook login:

FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:accessToken];

This method itself is not public as it seems to be part of the Core framework (please correct me if I am wrong). Hence, I do not know what it does exactly, however, I assume that it creates credentials with:

  1. Access token
  2. User ID
  3. Facebook app ID

The only problem which could arise with multiple Facebook apps is that user ID is unique for each app. However, Facebook itself has a guide on how developers could map users across their multiple apps. Hence, it really seems to me that multiple Facebook apps could be supported on a core level. It obviously requires merging data if user logins from multiple apps (because they are going to have several ids). However, as I understand it, Firebase already has a merge mechanism across providers. So, adding this logic would not be too difficult.

The alternative to having this at the core level is the following:

  1. Create custom authentication logic to get the access token. This is almost identical to the FUIFacebookAuth.
  2. Setup a server which will be able to process the access tokens.
  3. This might be easy, but I cannot yet understand what uid I would need to pass to the admin.auth().createCustomToken()
  4. Send generated Firebase tokens back to client
  5. Finish authentication

For my use case the manual flow is so difficult (maybe due to lack of experience with the back end) that I will probably stick to one facebook app and will only allow login through Facebook for one of our iOS apps.

I hope that at some point the support of multiple FB apps will be added to the core framework. It seems like this is the place where it should belong.

protocol86 commented 6 years ago

@AndriyGo

The credentialWithAccessToken: method on FIRFacebookAuthProvider isn't really magical. It creates an object with the valid FB access token which can then be used to signInWithCredential in the core library. Firebase's backend talks to FB with the credentials (App Id and secret) stored in the Firebase console. So adding support to the core library will have to entail adding support for additional FB credentials in the console as well as changing the backend logic.

As @bojeil-google pointed out this would need to be a multi-platform and backend effort on our side which deserves careful design as it could likely affect other existing flows. We are aware of this gap and appreciate you bringing it to light again; and we'll certainly address it when it bubbles to the top of our priority list.

AndriyGo commented 6 years ago

@protocol86

After more playing with the authentication, I think I figured out what I need to do and why the standard implementation is not able to deal with multiple FB apps. And in my opinion, this is related to a broader issue which should be addressed in the Firebase core.

The best way to support multiple FB apps is to follow this logic whenever a user signs into FB app:

1) User signs into FB app and gets an access token. 2) This token is now used to obtain id and token_for_business (if it is set) from FB. 3) If token_for_business exists, we need to try to find an auth instance which has the UID equal to token_for_business 4) If we find such user, it means that it is the same user. Otherwise, the user is new 5) In either case, in addition to having UID equal to token_for_business we need to store the id of the user from Facebook. Otherwise, we will not be able to query any other info about the user on FB.

Step 5 is the reason why currently Firebase cannot work with multiple FB apps. It doesn't allow the storage of custom attributes. Hence, there is no way to store token_for_business and id from facebook at the same time. Is there a good reason to have this limitation in the Firebase Core? Setting custom attributes is useful in many cases, not just this one. For example, one could add fields such as birthday, first/last name, etc. At the moment this needs to be added to the real-time database or Firestore. However, it would be good to have all of this info in the auth table. Though maybe I am missing the reason why it is not a good idea to have all of this info in the auth table 😄

On a side note, I have the question about UIDs which is not directly related to this issue. If I generate some UID as part of custom authentication, how do I ensure that it is unique and is not equal to UID generated by some other provider? One way to do it would be to append some prefix (e.g "fb_") to my UID. Or is this done automatically by Firebase? It does store the provider ID so I thought that it might be trying to authenticate by checking if there is a user whose UID is XXXX for Provider YYYY.

katehaber commented 5 years ago

@AndriyGo did you ever come up with a solution to this issue? encountering the same exact problem now and looking for potential solutions. thanks.

iliev-io commented 5 years ago

@AndriyGo we have a similar use case and I think I found a solution which might work. It is completely done out of Firebase, which is why it might work. We're still testing to see if it will work, but it looks promising so far :)

We have 4 apps (iOS paid, iOS freemium, Android paid, Android freemium) which share the same login and we want users to be able to login with the same Firebase user id on all apps. All our apps share the same Facebook App Id.

We were running into the problem where we can't advertise on Facebook more than one app at a time and on top of that we were for example advertising our paid iOS app, getting installs to the free iOS app and these were being counted as conversions from Facebook.

I came up with an idea to create a Facebook App ID, which will be used only for marketing.

Here's a chart I made to better explain this to the rest of my team: Facebook App ID Chart

We're running this test since yesterday. Like I said, so far it seems to be working fine. We've also connected this new Facebook App ID to our attribution partner (Adjust) and their data also seems to be finally correct.

I'll update this once I have more data to share. Hope it helps you as well!

ghost commented 3 years ago

@AndriyGo we have a similar use case and I think I found a solution which might work. It is completely done out of Firebase, which is why it might work. We're still testing to see if it will work, but it looks promising so far :)

We have 4 apps (iOS paid, iOS freemium, Android paid, Android freemium) which share the same login and we want users to be able to login with the same Firebase user id on all apps. All our apps share the same Facebook App Id.

We were running into the problem where we can't advertise on Facebook more than one app at a time and on top of that we were for example advertising our paid iOS app, getting installs to the free iOS app and these were being counted as conversions from Facebook.

I came up with an idea to create a Facebook App ID, which will be used only for marketing.

Here's a chart I made to better explain this to the rest of my team: Facebook App ID Chart

We're running this test since yesterday. Like I said, so far it seems to be working fine. We've also connected this new Facebook App ID to our attribution partner (Adjust) and their data also seems to be finally correct.

I'll update this once I have more data to share. Hope it helps you as well!

Hi, does this still work? I tried implementing it like this but it looks like on the app side, FB can only init with one app id. I'm wondering how you got this to work two?

iliev-io commented 3 years ago

@AndriyGo we have a similar use case and I think I found a solution which might work. It is completely done out of Firebase, which is why it might work. We're still testing to see if it will work, but it looks promising so far :) We have 4 apps (iOS paid, iOS freemium, Android paid, Android freemium) which share the same login and we want users to be able to login with the same Firebase user id on all apps. All our apps share the same Facebook App Id. We were running into the problem where we can't advertise on Facebook more than one app at a time and on top of that we were for example advertising our paid iOS app, getting installs to the free iOS app and these were being counted as conversions from Facebook. I came up with an idea to create a Facebook App ID, which will be used only for marketing. Here's a chart I made to better explain this to the rest of my team: Facebook App ID Chart We're running this test since yesterday. Like I said, so far it seems to be working fine. We've also connected this new Facebook App ID to our attribution partner (Adjust) and their data also seems to be finally correct. I'll update this once I have more data to share. Hope it helps you as well!

Hi, does this still work? I tried implementing it like this but it looks like on the app side, FB can only init with one app id. I'm wondering how you got this to work two?

Hi. I missed this earlier. We only used the newly created Facebook App IDs for marketing purposes (paid FB ads). We kept the main Facebook App ID for login. And in the apps we only had one FB App ID.

So, if you want to use more than one FB ID in Firebase, it won't work simply because you can have only one App Store ID in the FB App.

One thing you could try is initialising the FB SDK with different FB App IDs depending on which app you're loading. You could do this by creating different targets in your apps and initialising them with separate config files.