facebook / facebook-ios-sdk

Used to integrate the Facebook Platform with your iOS & tvOS apps.
https://developers.facebook.com/docs/ios
Other
7.8k stars 3.56k forks source link

"GraphAPI, iOS" via Limited Login has inconsistent behavior and inconsistent documentation #2446

Open lucavenir opened 5 months ago

lucavenir commented 5 months ago

Checklist before submitting a bug report

Xcode version

15.4

Facebook iOS SDK version

17.0.2

Dependency Manager

CocoaPods

SDK Framework

Core

Goals

On registration, we'd like to extract first name and last name from every login provider, e.g. facebook, as much as possible.

I read about the latest iOS changes in your blog post. All my users will use limited login, as people won't be happy to be "tracked" just because of a simple login. Therefore, I read the documentation and the post above thoroughly.

Such post says:

However, if you do not integrate Limited Login, you will need to handle all Graph API calls using Graph API, iOS.

This is what things get weird. The documentation pointed above clearly suggest that with Limited Login, Graph API won't work. ... but your most recent blog post just stated that it would be possible to extract basic information from graph api, as long as we make requests via the GraphAPI, iOS SDK.

This contradiction is making us uncomfortable. But things get even weirder if you actually try the to use the API: indeed, this is a bug report and not just a question. See the experiment below.

Expected results

The docs suggest this quick snippet to start, which is very straighforward:

guard AccessToken.current != nil else { return }

let request = GraphRequest(graphPath: "me", parameters: [:])
request.start() { connection, result, error in
    if let result = result, error == nil {
        print("fetched user: \(result)")
    }
}

As I've already said, this code makes it clear that it can't be possible to make requests without an access token. Indeed, we cannot obtain an access token via limited logins. Only authentication tokens are given in that case. This is the only coherent and actual behavior we've found so far.

... what happens if the remove the guard above? You know, just to see if the blog post makes sense. Well, here's what happens. The following code (without the access token check):

let request = GraphRequest(graphPath: "me", parameters: [:])
request.start() { connection, result, error in
    if let result = result, error == nil {
        print("fetched user: \(result)")
    }
}

... will fail on older devices, e.g. iPhone 7 with iOS 15. The error message in here, contradicts with the blog post, but confirms what the documentation suggests:

error: Error
    Domain=com.facebook.sdk.core
    Code=8 "(null)"
    UserInfo={
        com.facebook.sdk:FBSDKGraphRequestErrorGraphErrorCodeKey=2500,
        com.facebook.sdk:FBSDKGraphRequestErrorHTTPStatusCodeKey=400,
        com.facebook.sdk:FBSDKGraphRequestErrorParsedJSONResponseKey={
            body =     {
                error =         {
                    code = 2500;
                    "fbtrace_id" = "Anjq7_2ehmpXBL_7iu2CNQ4";
                    message = "An active access token must be used to query information about the current user.";
                    type = OAuthException;
                };
            };
            code = 400;
        },
        com.facebook.sdk:FBSDKErrorDeveloperMessageKey=An active access token must be used to query information about the current user.,
        com.facebook.sdk:FBSDKGraphRequestErrorKey=0
}

This is fine. Maybe the blog post is simply wrong, or I misinterpreted it. But...

Actual results

... but what happens if you execute that identical experiments on iOS 17?

Well, the same identical snippet will succeed for users using iOS 17. The API correctly outputs e.g. first name and last name. So... this behavior seem to confirm what the latest blog post stated. But clearly contradicts the documentation.

Now - who's right? No one is. This is not just a documentation issue. Your SDK give different results based on the device / iOS version. What are we missing, here?

By the way, yes, both tests never asked tracking permissions to the user and no tracking permission is ever granted to our app.

What we need is:

  1. clear and unified documentation and statements about the relationship between limited login and graph APIs; correct the blog post if necessary
  2. consistent behavior between multiple iOS versions and effortless integration

Steps to reproduce

As stated above, here's the step to reproduce the experiment:

  1. Perform a limited login
  2. With a limited-logged in user, follow this guide and write down that snippet
  3. Before executing it, remove the guard part, so that the request is sent even though AccessToken isn't present

Now, you'll get two different and incoherent behaviors:

Code samples & details

No response