facebookarchive / react-native-fbsdk

A React Native wrapper around the Facebook SDKs for Android and iOS. Provides access to Facebook login, sharing, graph requests, app events etc.
https://developers.facebook.com/docs/react-native
Other
2.99k stars 910 forks source link

[iOS] Native Facebook App Authentication #734

Open lucasgismondi opened 4 years ago

lucasgismondi commented 4 years ago

I'm seeing from others that it is possible to login through the Facebook app for iOS but I can't seem to get it to work. I've tried adding

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
  if ([[FBSDKApplicationDelegate sharedInstance] application:application openURL:URL options:options]) {
    return YES;
  }
  return NO;
}

but the webview shows when pressing Log In. There's also no way for me to check if this works because I'm not able to sign into a different Facebook account after I've already logged in. Has anyone successfully been able to do this? Am I missing something? Is it even possible? Is there something I need to add in my info.plist?

react-native-fbsdk: v1.1.1 react-native: v0.61.4

Thanks!

eroy4u commented 4 years ago

Encounter the same issue. Cannot use Facebook app to log in.

shmagdy commented 4 years ago

same issue

Jani-10thmuse commented 4 years ago

we have same issue

mralj commented 4 years ago

We have same issue, everything works fine unless you have installed Facebook app on your phone (which I guess most of the people do), FB Login Flow is broken, meaning

  1. I tap on "Login with FB"
  2. Modal which displays FB's Web page is opened, there is button "Login With the Facebookapp"
  3. I tap on that, I am taken to FB native app, there is button "Continue"
  4. I tap on that, I am taken back to point 2. (ie. modal with Web page)

And that basically it, like infinite loop which I can only "exit" by exiting whole "flow", thus not being able to Login with FB

I have tested this on both Simulator and device where Facebook app was NOT installed, then login process was done via "web" and it worked as expected.

lucasgismondi commented 4 years ago

@mralj Did you do anything specific to get the "Login With the Facebook app" to show in the web page that pops up??

mralj commented 4 years ago

Nope, we are not doing anything "on the native side", and here is our code:

  LoginManager.logInWithPermissions(["email"]).then(
    result => {
      const userCanceledFbLoginProcess = !!result && result.isCancelled;
      if (userCanceledFbLoginProcess) {
        return;
      }
      AccessToken.getCurrentAccessToken().then(
        fbResponse => {
          if (!!fbResponse) {
            updateUserProfileWithDataFromFB(fbResponse);
          }
        },
        tokenError => {
          if (!!tokenError) {
            setImmediateErrorAlert("common.fbErrors.cantLoginWithFacebook");
            logError({ error: tokenError });
          }
        }
      );
    },
    error => {
      setImmediateErrorAlert("common.fbErrors.initialProcessingError");
      logError({ error });
    }
  );
mralj commented 4 years ago

Me again 🙂

I have realized that I have proably misunderstood OP and that we have actually different issues, mine being not "infinite loop" when FB app installed, and OP's being that FB app,event hough installed is not opened during Login process (and in my scenario FB app is being opened and that caused trouble).

Since the FB app is opening for me, and I have fixed issue I was having, I'm sharing our "setup".

JS code is already posted above, so here are 2 other relevatnt files:

Info.plst

Key Type Value
FacebookAdvertiserIDCollectionEnabled Booelan Yes
FacebookAppID String YOUR_FB_APP_ID
FacebookAutoLogAppEventsEnabled Boolean Yes
FacebookDisplayName String $(PRODUCT_NAME)

AppDelegate.m

In application didFinishLaunchingWithOptions I have

[[FBSDKApplicationDelegate sharedInstance] application:application
                           didFinishLaunchingWithOptions:launchOptions];

And adding this fixed issue for me (I think this was needed due to th fact I am using RNN)

- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  if ([[FBSDKApplicationDelegate sharedInstance] application:app openURL:url options:options]) {
    return YES;
  }

  return NO;
}

Regarding this:

There's also no way for me to check if this works because I'm not able to sign into a different Facebook account after I've already logged in.

Maybe stupid question, but I am not sure why can't you simply logout (and then sign into another account ?

When I was testing this, I was loging-in via Tests users. If you were unaware of this feature, here are steps to create them:

  1. You go to: https://developers.facebook.com
  2. From "My apps" drop-down select your app
  3. Go to Roles > Test users
  4. Add some test users :) (by clicking edit you can change stuff like password for that test user etc.)

When you are "done" with that account you can simply delete it and choose another one.

If you were testing with your personal FB account, here are my suggestions on "logging out":

  1. Go to settings > Apps and Websites > Find your app > Select it > Tap on Remove
  2. (this actually logs you out) Settings > Security And Login > Find device(s) from which you want to log out, tap "menu icon" > Log out

Hope this helps 😄

snowloop commented 4 years ago

The solution above worked for me ! The facebook SDK documentation should be updated

ZChenzy commented 4 years ago

We have same issue, everything works fine unless you have installed Facebook app on your phone (which I guess most of the people do), FB Login Flow is broken, meaning

  1. I tap on "Login with FB"
  2. Modal which displays FB's Web page is opened, there is button "Login With the Facebookapp"
  3. I tap on that, I am taken to FB native app, there is button "Continue"
  4. I tap on that, I am taken back to point 2. (ie. modal with Web page)

And that basically it, like infinite loop which I can only "exit" by exiting whole "flow", thus not being able to Login with FB

I have tested this on both Simulator and device where Facebook app was NOT installed, then login process was done via "web" and it worked as expected.

Did you ever resolve this issue? I am running into this issue

mralj commented 4 years ago

Yes, as stated above:

And adding this fixed issue for me (I think this was needed due to the fact I am using RNN)

- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  if ([[FBSDKApplicationDelegate sharedInstance] application:app openURL:url options:options]) {
    return YES;
  }

  return NO;
}
creativemind1 commented 4 years ago

Yes, as stated above:

And adding this fixed issue for me (I think this was needed due to the fact I am using RNN)

- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  if ([[FBSDKApplicationDelegate sharedInstance] application:app openURL:url options:options]) {
    return YES;
  }
 
  return NO;
}

My scenario is:

mralj commented 4 years ago

I am by no means expert in this, but, according to these (link1 & link2), this error was known to happen on FB SDK side, we are running v1.1.2 (of this plugin) and everything seems t be working fine.

Could you try downgrading and check if issue is still there ?

mralj commented 4 years ago

I have updated react-native-fbsdk in our project to latest version (v2.0.0), and for me everything works fine.

I have tested on 2 devices (and 2 different scenarios), both devices running iOS 13, both builds were release :

1st scenario was:

2nd scenario was:

So good news is, everything works as expected 🙂 Bad news is I have no idea why SDK doesn't work for you 🤷‍♂️😕

P.S.

Obviously this has nothing to do with this particular issue, but also tested on Android "while I was at it", also works :)

creativemind1 commented 4 years ago

It's good to see it's working for you. If I'm not bugging you much, would you please care to look at my AppDelegate.m file.

#import "AppDelegate.h"
#import <Firebase.h>
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <React/RCTLinkingManager.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [FIRApp configure];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
  [FBSDKAppEvents activateApp];
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
  return [[FBSDKApplicationDelegate sharedInstance] application:application
                                                         openURL:url
                                               sourceApplication:sourceApplication
                                                      annotation:annotation];
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
  [super applicationWillEnterForeground:application];
}

#pragma mark - Background Fetch

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [super application:application performFetchWithCompletionHandler:completionHandler];
}

#pragma mark - Handling URLs

- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{

if ([[FBSDKApplicationDelegate sharedInstance] application:application openURL:url options:options]) {
    return YES;
  }

  if ([RCTLinkingManager application:application openURL:url options:options]) {
    return YES;
  }

  return NO;
}

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
  return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
}

#pragma mark - Notifications

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)token
{
  [super application:application didRegisterForRemoteNotificationsWithDeviceToken:token];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)err
{
  [super application:application didFailToRegisterForRemoteNotificationsWithError:err];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
  [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

@end
mralj commented 4 years ago

TBH I have no idea, your AppDelegate file is. much more complicated than ours, and I have no experience in iOS development / Objective-C.

This is wild shot in the dark, but it looks to me that you have polymorphic openURL

1

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
  return [[FBSDKApplicationDelegate sharedInstance] application:application
                                                         openURL:url
                                               sourceApplication:sourceApplication
                                                      annotation:annotation];
}

and

2

- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{

if ([[FBSDKApplicationDelegate sharedInstance] application:application openURL:url options:options]) {
    return YES;
  }

  if ([RCTLinkingManager application:application openURL:url options:options]) {
    return YES;
  }

  return NO;
}

Looking at iOS source code I found this:

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation API_DEPRECATED_WITH_REPLACEMENT("application:openURL:options:", ios(4.2, 9.0)) API_UNAVAILABLE(tvos);

typedef NSString * UIApplicationOpenURLOptionsKey NS_TYPED_ENUM;

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options API_AVAILABLE(ios(9.0)); // no equiv. notification. return NO if the application can't open for some reason

Could it be that first one is causing problem ? if I am reading code correctly, isn't 1st method deprecated (on iOS 9+) ?

creativemind1 commented 4 years ago

yes it is deprecated. In fact, it is showing in my Xcode as well. Also FBSDKCoreKit using the same openURL deprecated code. But why the module is showing that? Do you think this could be the issue?

mralj commented 4 years ago

Maybe stupid question, but can’t you simply delete it and see if everything works ?

The openUrl scenario should be covered by 2nd “case”

creativemind1 commented 4 years ago

Ok I will give this a try. Just a last question if you don't mind, I have not added swift dependency from this URL https://github.com/facebook/facebook-ios-sdk. as shown in the facebo?ok Get Started Link. Is it compulsory

mralj commented 4 years ago

I don't think it is necessary to addd that dependency, IMHO, you should only follow steps from this library. For us everything worked fine by just following those steps. This way react-native-fbsdk will take care of adding all deps needed.

Here is example from our Podfile.lock:

- FBSDKCoreKit (7.0.0):
    - FBSDKCoreKit/Basics (= 7.0.0)
    - FBSDKCoreKit/Core (= 7.0.0)
  - FBSDKCoreKit/Basics (7.0.0)
  - FBSDKCoreKit/Core (7.0.0):
    - FBSDKCoreKit/Basics
  - FBSDKLoginKit (7.0.0):
    - FBSDKLoginKit/Login (= 7.0.0)
  - FBSDKLoginKit/Login (7.0.0):
    - FBSDKCoreKit (~> 7.0.0)
  - FBSDKShareKit (7.0.0):
    - FBSDKShareKit/Share (= 7.0.0)
  - FBSDKShareKit/Share (7.0.0):
    - FBSDKCoreKit (~> 7.0.0)**

As you can see we are not using "Swift version"

creativemind1 commented 4 years ago

My bad. The issue was there in my Info.plist file. I had to change the boolean value of FacebookAutoInitEnabled to true and it is now working fine. Now even my Facebook Pixel events are working. So these are my changes:

<key>FacebookAdvertiserIDCollectionEnabled</key>
<true/>
<key>FacebookAutoLogAppEventsEnabled</key>
<true/>
<key>FacebookAutoInitEnabled</key>
<true/>

Your help was very appreciated, thanks. @mralj