开发者

Does the Facebook iOS SDK require the user to authenticate every time they use the app?

开发者 https://www.devze.com 2023-02-22 19:21 出处:网络
As described in the README for facebook-i开发者_开发技巧os-sdk, my app calls Facebook#authorize:delegate: before performing any API calls.

As described in the README for facebook-i开发者_开发技巧os-sdk, my app calls Facebook#authorize:delegate: before performing any API calls.

This method requires the user to authenticate (either in the Facebook app or in Safari) and then drops control back to my iPhone app. The problem is it asks the user to authenticate every time I call the method. If they've already granted permission to my app, they get a message saying that the app is already authorized and they have to press Okay to go back to my app. It doesn't look very professional.

So I have two questions:

  1. Does the user always have to reauthorize in order to make Facebook calls? I always thought it would save the access token somewhere, maybe in the user defaults, so that you wouldn't need to reauthorize.

  2. If the user doesn't have to reauthorize every time, is there a way to check if my app already has permission, so the user doesn't have to see that message and press Okay?


It's unfortunate that the Facebook SDK doesn't automatically handle it for us. Aside from building it into the SDK yourself, the easiest way is as such:

Each time you allocate _facebook:

_facebook = [[Facebook alloc] initWithAppId:@"SuperDuperAppID"];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *accessToken = [prefs stringForKey:@"facebook-accessToken"];
NSString *expirationDate = [prefs stringForKey:@"facebook-expirationDate"];
_facebook.accessToken = accessToken;
_facebook.expirationDate = expirationDate;

If you've never saved anything in the NSUserDefaults, then nil values will be set. Nothing's happened. Otherwise, true values will be set, and [_facebook isSessionValid]; should return TRUE, indicating good values. Go ahead and make Facebook SDK calls as if they are logged in (which they are). If false, then call

[facebook authorize:permissions delegate:self]; 

as usual.

Then make sure to support the following Facebook delegate method:

- (void)fbDidLogin {
NSString *accessToken = _facebook.accessToken;
NSString *expirationDate = _facebook.expirationDate;
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:accessToken forKey:@"facebook-accessToken"];
[prefs expirationDate forKey:@"facebook-expirationDate"];
[prefs synchronize];
}

I use this code in my app, and it works perfectly. I did this from memory, so I apologize if it doesn't work on copy-and-paste. There might be a mistype somewhere, plus improper memory management. Don't forget that access tokens expire unless you get offline permission. In any case the code above handles everything.


The problem is it asks the user to authenticate every time I call the method. If they've already granted permission to my app, they get a message saying that the app is already authorized and they have to press Okay to go back to my app.

1) Does the user always have to reauthorize in order to make Facebook calls? I always thought it would save the access token somewhere, maybe in the user defaults, so that you wouldn't need to reauthorize.

The cause of having to go through the sign on process every time is that, after successfully signing on the first time, the Facebook SDK doesn't save the access token in a persistent manner.

2) If the user doesn't have to reauthorize every time, is there a way to check if my app already has permission, so the user doesn't have to see that message and press Okay?

The fact that the Facebook SDK doesn't save the access token doesn't mean you can't do it yourself. The following code ilustrates how to save/retrieve the access token from the NSUserDefaults.

-(void)login {
    // on login, use the stored access token and see if it still works
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    facebook.accessToken = [defaults objectForKey:ACCESS_TOKEN_KEY];
    facebook.expirationDate = [defaults objectForKey:EXPIRATION_DATE_KEY];

    // only authorize if the access token isn't valid
    // if it *is* valid, no need to authenticate. just move on
    if (![facebook isSessionValid]) {
        NSArray * permissions = [NSArray arrayWithObjects:@"read_stream", @"offline_access", @"email", nil];
        [facebook authorize:permissions delegate:self];
    }
}

/**
 * Called when the user has logged in successfully.
 */
- (void)fbDidLogin {
    // store the access token and expiration date to the user defaults
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:facebook.accessToken forKey:ACCESS_TOKEN_KEY];
    [defaults setObject:facebook.expirationDate forKey:EXPIRATION_DATE_KEY];
    [defaults synchronize];
}


When the user logs in, you'll get an access token and an expiry date. Save the access token and you can reuse it as long as you haven't hit the expiry date yet. The Facebook SDK has a method to do this check: [fbConnect isSessionValid] but it seems to give false positives sometimes, so I have the user log in if a request fails.


1) No, I had to do Facebook *fbConnect = [[Facebook alloc] init]; [fbConnect logout:self]; to get the user session away

2) I suppose you could call the accestoken in Facebook.m to check that


Here is more actual approach of @Daniel Amitay answer:
In view controller with login button you write

//saving user data to user defaults in order to support Facebook SSO
let token = FBSDKAccessToken.currentAccessToken()
let prefs = NSUserDefaults.standardUserDefaults()
let nsdataToken = NSKeyedArchiver.archivedDataWithRootObject(token)
prefs.setObject(nsdataToken, forKey: "facebook-AccessToken")
prefs.synchronize()

In AppDelegate file func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool you write following

//restoring Facebook SSO session from user defaults
let prefs = NSUserDefaults.standardUserDefaults()
if let nsdataToken = prefs.valueForKey("facebook-AccessToken") as? NSData {
    let token = NSKeyedUnarchiver.unarchiveObjectWithData(nsdataToken) as! FBSDKAccessToken
    FBSDKAccessToken.setCurrentAccessToken(token)
}
0

精彩评论

暂无评论...
验证码 换一张
取 消