Skip to content
Browse files

Add FBSession handleDidBecomeActive to better handle scenarios where …

…users decline or do not complete app-switch authorizations.

Summary:
Add FBSession handleDidBecomeActive to better handle scenarios where users
decline or do not complete app-switch authorizations. Consumers should call
this method from their application delegate's 'applicationDidBecomeActive:'
in a similar way as the 'handleOpenUrl:'.

This method uses new internal state to clean up any incomplete (re)
authorizations and takes into account the new iOS 6 system authorization.

Test Plan:
I. Ran unit tests in sdk core.
II. Scrumptious testing
 (Test Matrix) For:
1) ios6 device with system authorization
2) ios6 device w/o system authorization but with facebook app login
3) ios6 simulator using safari login fallback

 performed:
a) login->accept auth; post->accept auth; verify post.
b) login->decline/ignore; re-open app->login again; verify app state.
c) after login; post->decline/ignore auth; verify app state;
   post again->accept auth; verify post.

III. Verified SessionLoginSample

Revert Plan:

Reviewers: jacl, clang

Reviewed By: jacl

Differential Revision: https://phabricator.fb.com/D582040

Task ID: 1752513
  • Loading branch information...
1 parent e85ada7 commit 2f449d5590846fc9c3f3d93b044e41e4accb4340 @chrisp-fb chrisp-fb committed
View
7 samples/HelloFacebookSample/HelloFacebookSample/HFAppDelegate.m
@@ -62,4 +62,11 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
return YES;
}
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ // FBSample logic
+ // We need to properly handle activation of the application with regards to SSO
+ // (e.g., returning from iOS 6.0 authorization dialog or from fast app switching).
+ [FBSession.activeSession handleDidBecomeActive];
+}
+
@end
View
17 samples/Scrumptious/scrumptious/SCAppDelegate.m
@@ -131,7 +131,7 @@ - (BOOL)application:(UIApplication *)application
// FBSample logic
// We need to handle URLs by passing them to FBSession in order for SSO authentication
// to work.
- return [FBSession.activeSession handleOpenURL:url];
+ return [FBSession.activeSession handleOpenURL:url];
}
- (void)applicationWillTerminate:(UIApplication *)application {
@@ -142,16 +142,13 @@ - (void)applicationWillTerminate:(UIApplication *)application {
[FBSession.activeSession close];
}
-- (void)applicationDidBecomeActive:(UIApplication *)application {
- // this means the user switched back to this app without completing a login in Safari/Facebook App
- if (FBSession.activeSession.state == FBSessionStateCreatedOpening) {
- // BUG: for the iOS 6 preview we comment this line out to compensate for a race-condition in our
- // state transition handling for integrated Facebook Login; production code should close a
- // session in the opening state on transition back to the application; this line will again be
- // active in the next production rev
- //[FBSession.activeSession close]; // so we close our session and start over
- }
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ // FBSample logic
+ // We need to properly handle activation of the application with regards to SSO
+ // (e.g., returning from iOS 6.0 authorization dialog or from fast app switching).
+ [FBSession.activeSession handleDidBecomeActive];
}
+
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// BUG WORKAROUND:
// Nib files require the type to have been loaded before they can do the
View
11 samples/SessionLoginSample/SessionLoginSample/SLAppDelegate.m
@@ -84,14 +84,9 @@ Restart any tasks that were paused (or not yet started) while the application wa
*/
// FBSample logic
- // this means the user switched back to this app without completing a login in Safari/Facebook App
- if (self.session.state == FBSessionStateCreatedOpening) {
- // BUG: for the iOS 6 preview we comment this line out to compensate for a race-condition in our
- // state transition handling for integrated Facebook Login; production code should close a
- // session in the opening state on transition back to the application; this line will again be
- // active in the next production rev
- //[self.session close]; // so we close our session and start over
- }
+ // We need to properly handle activation of the application with regards to SSO
+ // (e.g., returning from iOS 6.0 authorization dialog or from fast app switching).
+ [FBSession.activeSession handleDidBecomeActive];
}
#pragma mark Template generated code
View
8 src/FBSession.h
@@ -394,6 +394,14 @@ typedef void (^FBSessionReauthorizeResultHandler)(FBSession *session,
- (BOOL)handleOpenURL:(NSURL*)url;
/*!
+ @abstract
+ A helper method that is used to provide an implementation for
+ [UIApplicationDelegate applicationDidBecomeActive:] to properly resolve session state for
+ the Facebook Login flow, specifically to support app-switch login.
+*/
+- (void)handleDidBecomeActive;
+
+/*!
@methodgroup Class methods
*/
View
49 src/FBSession.m
@@ -87,6 +87,8 @@ @interface FBSession () <FBLoginDialogDelegate> {
BOOL _isInStateTransition;
BOOL _isFacebookLoginToken;
BOOL _isOSIntegratedFacebookLoginToken;
+ BOOL _isPendingReauthorization;
+ BOOL _isPendingOpenUrlCallback;
FBSessionDefaultAudience _defaultDefaultAudience;
}
@@ -246,6 +248,8 @@ - (id)initWithAppID:(NSString*)appID
// additional setup
_isInStateTransition = NO;
_isFacebookLoginToken = NO;
+ _isPendingReauthorization = NO;
+ _isPendingOpenUrlCallback = NO;
_isOSIntegratedFacebookLoginToken = NO;
_defaultDefaultAudience = defaultAudience;
self.attemptedRefreshDate = [NSDate distantPast];
@@ -430,7 +434,8 @@ - (BOOL)handleOpenURL:(NSURL *)url {
if (![[url absoluteString] hasPrefix:self.appBaseUrl]) {
return NO;
}
-
+ _isPendingOpenUrlCallback = NO;
+
// version 3.2.3 of the Facebook app encodes the parameters in the query but
// version 3.3 and above encode the parameters in the fragment; check first for
// fragment, and if missing fall back to query
@@ -441,7 +446,7 @@ - (BOOL)handleOpenURL:(NSURL *)url {
NSDictionary *params = [FBUtility dictionaryByParsingURLQueryPart:query];
NSString *accessToken = [params objectForKey:@"access_token"];
-
+
switch (self.state) {
case FBSessionStateCreatedOpening:
return [self handleOpenURLPreOpen:params
@@ -456,6 +461,36 @@ - (BOOL)handleOpenURL:(NSURL *)url {
}
}
+- (void)handleDidBecomeActive{
+ //Unexpected to calls to app delegate's applicationDidBecomeActive are
+ // handled by this method. If a pending fast-app-switch [re]authorization
+ // is in flight, it is cancelled. Otherwise, this method is a no-op.
+
+ const FBSessionState state = FBSession.activeSession.state;
+
+ if (state == FBSessionStateCreated ||
+ state == FBSessionStateClosed ||
+ state == FBSessionStateClosedLoginFailed){
+ return;
+ }
+
+ if (_isPendingOpenUrlCallback){
+ if (state == FBSessionStateCreatedOpening){
+ //if we're here, user had declined a fast app switch login.
+ [FBSession.activeSession close];
+ }
+ else if (_isPendingReauthorization){
+ //this means the user declined a 'reauthorization' so we need
+ // to clean out the in-flight request.
+ NSError *error = [FBSession errorLoginFailedWithReason:FBErrorReauthorizeFailedReasonUserCancelled
+ errorCode:nil
+ innerError:nil];
+ [self callReauthorizeHandlerAndClearState:error];
+ }
+ _isPendingOpenUrlCallback = NO;
+ }
+}
+
- (BOOL)isOpen {
return FB_ISSESSIONOPENWITHSTATE(self.state);
}
@@ -854,6 +889,8 @@ - (void)authorizeWithPermissions:(NSArray*)permissions
}
NSString *urlPrefix = [NSString stringWithFormat:@"%@://%@", scheme, FBAuthURLPath];
NSString *fbAppUrl = [FBRequest serializeURL:urlPrefix params:params];
+
+ _isPendingOpenUrlCallback = YES;
didAuthNWithSystemAccount = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:fbAppUrl]];
}
@@ -862,8 +899,13 @@ - (void)authorizeWithPermissions:(NSArray*)permissions
[params setValue:nextUrl forKey:@"redirect_uri"];
NSString *fbAppUrl = [FBRequest serializeURL:loginDialogURL params:params];
+ _isPendingOpenUrlCallback = YES;
didAuthNWithSystemAccount = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:fbAppUrl]];
}
+ //In case openURL failed, make sure we don't still expect a openURL callback.
+ if (!didAuthNWithSystemAccount){
+ _isPendingOpenUrlCallback = NO;
+ }
}
// If single sign-on failed, see if we should attempt to fallback
@@ -1235,6 +1277,7 @@ - (void)reauthorizeWithPermissions:(NSArray*)permissions
// setup handler and permissions and perform the actual reauthorize
self.reauthorizePermissions = permissions;
self.reauthorizeHandler = handler;
+ _isPendingReauthorization = YES;
[self authorizeWithPermissions:permissions
behavior:behavior
defaultAudience:audience
@@ -1375,6 +1418,8 @@ - (void)transitionAndCallHandlerWithState:(FBSessionState)status
}
- (void)callReauthorizeHandlerAndClearState:(NSError*)error {
+ _isPendingReauthorization = NO;
+
// clear state and call handler
FBSessionReauthorizeResultHandler reauthorizeHandler = [self.reauthorizeHandler retain];
self.reauthorizeHandler = nil;

0 comments on commit 2f449d5

Please sign in to comment.
Something went wrong with that request. Please try again.