Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
638 views
in Technique[技术] by (71.8m points)

objective c - How to completely Logout of Facebook SDK Auth in iOS App

using FBSDKCoreKit 4.22.1

I have an app installed publicly, servicing multiple users during the day. A person can walk up to the iPad and login with their Facebook account:

enter image description here

After successful login, than can do their work and use the app and than they will logout some time later: enter image description here

The Logout happens successfully. Then the next user comes up to use the public iPad and clicks the Facebook Login button, yet they will see:enter image description here

The FBSDKLoginManager or other Facebook SDK Libs has remembered some elements of the previous user's Facebook login.

I want to completely clear out any information about the previous user's Facebook credentials

After successful Logout, this FBSDKLoginButtonDelegate method is called and I have tried the following to completely remove the Facebook account info with no success:

func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
    print("(#function) in (#file.components(separatedBy: "/").last ?? "")")
    print("Todo, must completely remove Facebook Auth token info for current user logging out")
    FBSDKAccessToken.setCurrent(nil)
    FBSDKLoginManager().logOut()
    FBSDKProfile.setCurrent(nil)
}

So with FBSDKCoreKit 4.22.1 Safari browser is used to open the Facebook authentication redirect URL and that Javascript uses local storage:enter image description here

Interestingly, Blocking all Cookies, which Apple implies will also block Website Data (localStorage), does NOT block local storage and Facebook and still create Web Site data stores: enter image description here

Apple says here:

"Change which cookies and website data are accepted: Select a “Cookies and website data” option:"

  • "Always block: Safari doesn’t let any websites, third parties, or advertisers store cookies and other data on your Mac. This may prevent some websites from working properly."

And that is where I expect Local Storage to be blocked as well as cookies but Facebook can still create local storage entries

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I had a similar issue and I ended up using a MODIFIED version of the SDK which is actually quite dangerous because another developer may not know that it was modified.. So you'd need to leave a note..

Issue: After you log out, you are still logged in (in Safari).. but only if you use Native login or System login, and there's no way to log out of Safari from within the app itself.. Super annoying (You cannot clear Safari's cookies or data from within the app either).

Solution(s):

If you look through the documentation for the SDK, it shows:

// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.




typedef NS_ENUM(NSUInteger, FBSDKLoginBehavior)
{
  /*!
   @abstract This is the default behavior, and indicates logging in through the native
   Facebook app may be used. The SDK may still use Safari instead.
   */
  FBSDKLoginBehaviorNative = 0,
  /*!
   @abstract Attempts log in through the Safari or SFSafariViewController, if available.
   */
  FBSDKLoginBehaviorBrowser,
  /*!
   @abstract Attempts log in through the Facebook account currently signed in through
   the device Settings.
   @note If the account is not available to the app (either not configured by user or
   as determined by the SDK) this behavior falls back to c FBSDKLoginBehaviorNative.
   */
  FBSDKLoginBehaviorSystemAccount,
  /*!
   @abstract Attemps log in through a modal c UIWebView pop up

   @note This behavior is only available to certain types of apps. Please check the Facebook
   Platform Policy to verify your app meets the restrictions.
   */
  FBSDKLoginBehaviorWeb,
};

So if you use Native but it can't, it will fallback to Safari. If you use System but it can't, it falls back to Native which falls back to Safari..

Then there's FBSDKLoginBehaviorWeb which uses a modal web-view/popup! So if you don't absolutely have to use Native or System Login, then I suggest you choose this option as it does NOT fall-back to Safari.

Otherwise: This is what I changed so that it NEVER uses Safari in the background:

FBLoginSDKManager.m:

- (void)logInWithBehavior:(FBSDKLoginBehavior)loginBehavior
{
  NSDictionary *loginParams = [self logInParametersWithPermissions:_requestedPermissions];

  void(^completion)(BOOL, NSString *, NSError *) = ^void(BOOL didPerformLogIn, NSString *authMethod, NSError *error) {
    if (didPerformLogIn) {
      [_logger startAuthMethod:authMethod];
      _performingLogIn = YES;
    } else {
      if (!error) {
        error = [NSError errorWithDomain:FBSDKLoginErrorDomain code:FBSDKLoginUnknownErrorCode userInfo:nil];
      }
      [self invokeHandler:nil error:error];
    }
  };

  switch (loginBehavior) {
    case FBSDKLoginBehaviorNative: {
      if ([FBSDKInternalUtility isFacebookAppInstalled]) {
        [FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:^(FBSDKServerConfiguration *serverConfiguration, NSError *loadError) {
          BOOL useNativeDialog = [serverConfiguration useNativeDialogForDialogName:FBSDKDialogConfigurationNameLogin];
          if (useNativeDialog && loadError == nil) {
            [self performNativeLogInWithParameters:loginParams handler:^(BOOL openedURL, NSError *openedURLError) {
              if (openedURLError) {
                [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
                                   formatString:@"FBSDKLoginBehaviorNative failed : %@
Trying FBSDKLoginBehaviorBrowser", openedURLError];
              }
              if (openedURL) {
                completion(YES, FBSDKLoginManagerLoggerAuthMethod_Native, openedURLError);
              } else {
                [self logInWithBehavior:FBSDKLoginBehaviorWeb];  //-- CHANGED BY BRANDON T.
              }
            }];
          } else {
            [self logInWithBehavior:FBSDKLoginBehaviorWeb];  //-- CHANGED BY BRANDON T.
          }
        }];
        break;
      }
        // intentional fall through.  -- CHANGED BY BRANDON T.
        [self logInWithBehavior:FBSDKLoginBehaviorWeb];  //-- CHANGED BY BRANDON T.
        break;
    }
    case FBSDKLoginBehaviorBrowser: {
      [self performBrowserLogInWithParameters:loginParams handler:^(BOOL openedURL,
                                                                    NSString *authMethod,
                                                                    NSError *openedURLError) {
        if (openedURL) {
          completion(YES, authMethod, openedURLError);
        } else {
          completion(NO, authMethod, openedURLError);
        }
      }];
      break;
    }
    case FBSDKLoginBehaviorSystemAccount: {
      [FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:^(FBSDKServerConfiguration *serverConfiguration, NSError *loadError) {
        if (serverConfiguration.isSystemAuthenticationEnabled && loadError == nil) {
          [self beginSystemLogIn];
        } else {
          [self logInWithBehavior:FBSDKLoginBehaviorNative];
        }
      }];
      completion(YES, FBSDKLoginManagerLoggerAuthMethod_System, nil);
      break;
    }
    case FBSDKLoginBehaviorWeb:
      [self performWebLogInWithParameters:loginParams handler:^(BOOL openedURL, NSError *openedURLError) {
        completion(openedURL, FBSDKLoginManagerLoggerAuthMethod_Webview, openedURLError);
      }];
      break;
  }
}

This makes it so that all native login or system login will fall-back to the modal-in-app UIWebView. Then you can clear the cookies when the log out and you'll be fine.. Delete All NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies and NSURLCache.sharedURLCache().removeAllCachedResponses() after logging out.

The obviously safest option is to never use the System or Native Login and instead always use: FBSDKLoginBehaviorWeb..


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...