how to refresh an oauth token when using the Facebook iPhone SDK

Viewed 7813

I'm using the Facebook SDK for iOS in my app: http://github.com/facebook/facebook-ios-sdk

The oAuth token expires after about 2 hours. How can I "refresh" the oAuth token without having to call the [Facebook authorize...] method again - which shows an empty Facebook dialog briefly if the user had previously logged in? What I want to avoid is requiring the user to re-login to FB each time they use the app - say, day to day.

I am already saving / restoring oAuth tokens when the app exits / starts. And I can check to see if the token is valid using [Facebook isSessionValid], or by checking the expire time on the token. But what to do if the token has expired? I've read that it is possible to "refresh" the token, but I don't understand how this is done.

I don't want to request "offline_access" permission, which would give me a "forever" token.

Help!?

6 Answers

Facebook's implementation of OAuth doesn't support token refresh.

You have 2 types of access_tokens in Facebook. Short term token, which is given by default and a long term token which is given if you request offline_access. If refresh token were supported, it was the same as giving a offline_access token for all apps.

As long as the user has an active facebook session on your web control, you can request a new access_token just by accessing https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=http://www.facebook.com/connect/login_success.html&response_type=token or probably some iOS SDK command that does the same (never worked with it so I can't tell). This kind of request will not ask the user to login again, but will use the previous session that was created during the first login.

As of today Facebook is supposed to refresh tokens automatically, requests to GraphAPI can be done without providing token string either (Facebook handles it under the hood).

Moreover, if it happens that user wasn't using app for a long time and his token managed to expire, on your next request to Graph API an alert will be shown by Facebook's SDK asking user to relogin (all that is handled by Facebook and when done - will return into FBSDKGraphRequest's closure).

enter image description here

However, if someone really has a reason to manually refresh access token, here's an example (Swift 4):

private var selfDestructableNotificationToken: NotificationTokenThatAutomaticallyRemovesObserver?
final class NotificationTokenThatAutomaticallyRemovesObserver: NSObject { // more info here: https://oleb.net/blog/2018/01/notificationcenter-removeobserver/
    let token: Any
    init(_ token: Any) { self.token = token }
    deinit { NotificationCenter.default.removeObserver(token) }
}

...

if let currentFBToken = FBSDKAccessToken.current() { // if this is a Facebook user, not an email-based user
    if FBSDKAccessToken.currentAccessTokenIsActive() { // and his token has not expired yet
        let token = NotificationCenter.default.addObserver(forName: NSNotification.Name.FBSDKAccessTokenDidChange, object: nil, queue: OperationQueue.main) { notification in
            if let userInfo = notification.userInfo, let refreshedToken = userInfo["FBSDKAccessToken"] as? FBSDKAccessToken {
                self.fbAccessToken = refreshedToken.tokenString
            } else {
                self.fbAccessToken = currentFBToken.tokenString // falling back to using an old token (better than none)
            }
        }
        self.selfDestructableNotificationToken = NotificationTokenThatAutomaticallyRemovesObserver(token)
        FBSDKAccessToken.refreshCurrentAccessToken { _, _, error in
            if let error = error {
                print("failed to refresh Facebook token with error \(error.localizedDescription)")
                self.fbAccessToken = currentFBToken.tokenString // falling back to an old token (better than none)
            }
        }
    } else if FBSDKAccessToken.current().isExpired { // unlucky user. Probably returned to the app after > 2 months break
        self.fbAccessToken = currentFBToken.tokenString // assigning expired token. Facebook will ask user to relogin as soon as we call Graph API with that expired token
    }
}
Related