Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge remote-tracking branch 'origin/expiringAccessTokens'
  • Loading branch information
Yariv Sadan committed Jan 18, 2012
2 parents 0fc1768 + 4969a99 commit 4aa2a66
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 52 deletions.
1 change: 0 additions & 1 deletion sample/Hackbook/Hackbook/APIResultsViewController.h
Expand Up @@ -19,7 +19,6 @@


@interface APIResultsViewController : UIViewController @interface APIResultsViewController : UIViewController
<FBRequestDelegate, <FBRequestDelegate,
FBSessionDelegate,
UITableViewDataSource, UITableViewDataSource,
UITableViewDelegate>{ UITableViewDelegate>{
NSMutableArray *myData; NSMutableArray *myData;
Expand Down
57 changes: 36 additions & 21 deletions sample/Hackbook/Hackbook/HackbookAppDelegate.m
Expand Up @@ -43,37 +43,44 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[navController.navigationBar setTintColor:[UIColor colorWithRed:0/255.0 [navController.navigationBar setTintColor:[UIColor colorWithRed:0/255.0
green:51.0/255.0 green:51.0/255.0
blue:102.0/255.0 blue:102.0/255.0
alpha:1.0]]; alpha:1.0]];
[navController.navigationBar setBarStyle:UIBarStyleBlackTranslucent]; [navController.navigationBar setBarStyle:UIBarStyleBlackTranslucent];
self.navigationController = navController; self.navigationController = navController;
[rootViewController release]; [rootViewController release];
[navController release]; [navController release];

// Initialize Facebook // Initialize Facebook
facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:rootViewController]; facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:rootViewController];


// Check and retrieve authorization information
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
}

// Initialize API data (for views, etc.) // Initialize API data (for views, etc.)
apiData = [[DataSet alloc] init]; apiData = [[DataSet alloc] init];

// Initialize user permissions // Initialize user permissions
userPermissions = [[NSMutableDictionary alloc] initWithCapacity:1]; userPermissions = [[NSMutableDictionary alloc] initWithCapacity:1];

// Override point for customization after application launch. // Override point for customization after application launch.
// Add the navigation controller's view to the window and display. // Add the navigation controller's view to the window and display.
self.window.rootViewController = self.navigationController; self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible]; [self.window makeKeyAndVisible];

// Check App ID: // Check App ID:
// This is really a warning for the developer, this should not // This is really a warning for the developer, this should not
// happen in a completed app // happen in a completed app
if (!kAppId) { if (!kAppId) {
UIAlertView *alertView = [[UIAlertView alloc] UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:@"Setup Error" initWithTitle:@"Setup Error"
message:@"Missing app ID. You cannot run the app until you provide this in the code." message:@"Missing app ID. You cannot run the app until you provide this in the code."
delegate:self delegate:self
cancelButtonTitle:@"OK" cancelButtonTitle:@"OK"
otherButtonTitles:nil, otherButtonTitles:nil,
nil]; nil];
[alertView show]; [alertView show];
[alertView release]; [alertView release];
Expand All @@ -83,15 +90,15 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
NSString *url = [NSString stringWithFormat:@"fb%@://authorize",kAppId]; NSString *url = [NSString stringWithFormat:@"fb%@://authorize",kAppId];
BOOL bSchemeInPlist = NO; // find out if the sceme is in the plist file. BOOL bSchemeInPlist = NO; // find out if the sceme is in the plist file.
NSArray* aBundleURLTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"]; NSArray* aBundleURLTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"];
if ([aBundleURLTypes isKindOfClass:[NSArray class]] && if ([aBundleURLTypes isKindOfClass:[NSArray class]] &&
([aBundleURLTypes count] > 0)) { ([aBundleURLTypes count] > 0)) {
NSDictionary* aBundleURLTypes0 = [aBundleURLTypes objectAtIndex:0]; NSDictionary* aBundleURLTypes0 = [aBundleURLTypes objectAtIndex:0];
if ([aBundleURLTypes0 isKindOfClass:[NSDictionary class]]) { if ([aBundleURLTypes0 isKindOfClass:[NSDictionary class]]) {
NSArray* aBundleURLSchemes = [aBundleURLTypes0 objectForKey:@"CFBundleURLSchemes"]; NSArray* aBundleURLSchemes = [aBundleURLTypes0 objectForKey:@"CFBundleURLSchemes"];
if ([aBundleURLSchemes isKindOfClass:[NSArray class]] && if ([aBundleURLSchemes isKindOfClass:[NSArray class]] &&
([aBundleURLSchemes count] > 0)) { ([aBundleURLSchemes count] > 0)) {
NSString *scheme = [aBundleURLSchemes objectAtIndex:0]; NSString *scheme = [aBundleURLSchemes objectAtIndex:0];
if ([scheme isKindOfClass:[NSString class]] && if ([scheme isKindOfClass:[NSString class]] &&
[url hasPrefix:scheme]) { [url hasPrefix:scheme]) {
bSchemeInPlist = YES; bSchemeInPlist = YES;
} }
Expand All @@ -101,21 +108,29 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
// Check if the authorization callback will work // Check if the authorization callback will work
BOOL bCanOpenUrl = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString: url]]; BOOL bCanOpenUrl = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString: url]];
if (!bSchemeInPlist || !bCanOpenUrl) { if (!bSchemeInPlist || !bCanOpenUrl) {
UIAlertView *alertView = [[UIAlertView alloc] UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:@"Setup Error" initWithTitle:@"Setup Error"
message:@"Invalid or missing URL scheme. You cannot run the app until you set up a valid URL scheme in your .plist." message:@"Invalid or missing URL scheme. You cannot run the app until you set up a valid URL scheme in your .plist."
delegate:self delegate:self
cancelButtonTitle:@"OK" cancelButtonTitle:@"OK"
otherButtonTitles:nil, otherButtonTitles:nil,
nil]; nil];
[alertView show]; [alertView show];
[alertView release]; [alertView release];
} }
} }

return YES; return YES;
} }


- (void)applicationDidBecomeActive:(UIApplication *)application {
// Although the SDK attempts to refresh its access tokens when it makes API calls,
// it's a good practice to refresh the access token also when the app becomes active.
// This gives apps that seldom make api calls a higher chance of having a non expired
// access token.
[[self facebook] extendAccessTokenIfNeeded];
}

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [self.facebook handleOpenURL:url]; return [self.facebook handleOpenURL:url];
} }
Expand Down
41 changes: 20 additions & 21 deletions sample/Hackbook/Hackbook/RootViewController.m
Expand Up @@ -103,7 +103,7 @@ - (void)showLoggedOut {
nameLabel.text = @""; nameLabel.text = @"";
// Get the profile image // Get the profile image
[profilePhotoImageView setImage:nil]; [profilePhotoImageView setImage:nil];

[[self navigationController] popToRootViewControllerAnimated:YES]; [[self navigationController] popToRootViewControllerAnimated:YES];
} }


Expand Down Expand Up @@ -245,19 +245,11 @@ - (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated]; [super viewWillAppear:animated];


HackbookAppDelegate *delegate = (HackbookAppDelegate *)[[UIApplication sharedApplication] delegate]; HackbookAppDelegate *delegate = (HackbookAppDelegate *)[[UIApplication sharedApplication] delegate];
// Check and retrieve authorization information
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:@"FBAccessTokenKey"]
&& [defaults objectForKey:@"FBExpirationDateKey"]) {
[delegate facebook].accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
[delegate facebook].expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
}
if (![[delegate facebook] isSessionValid]) { if (![[delegate facebook] isSessionValid]) {
[self showLoggedOut]; [self showLoggedOut];
} else { } else {
[self showLoggedIn]; [self showLoggedIn];
} }

} }


- (void)viewWillDisappear:(BOOL)animated { - (void)viewWillDisappear:(BOOL)animated {
Expand Down Expand Up @@ -315,6 +307,13 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath


} }


- (void)storeAuthData:(NSString *)accessToken expiresAt:(NSDate *)expiresAt {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:accessToken forKey:@"FBAccessTokenKey"];
[defaults setObject:expiresAt forKey:@"FBExpirationDateKey"];
[defaults synchronize];
}

#pragma mark - FBSessionDelegate Methods #pragma mark - FBSessionDelegate Methods
/** /**
* Called when the user has logged in successfully. * Called when the user has logged in successfully.
Expand All @@ -323,16 +322,16 @@ - (void)fbDidLogin {
[self showLoggedIn]; [self showLoggedIn];


HackbookAppDelegate *delegate = (HackbookAppDelegate *)[[UIApplication sharedApplication] delegate]; HackbookAppDelegate *delegate = (HackbookAppDelegate *)[[UIApplication sharedApplication] delegate];
[self storeAuthData:[[delegate facebook] accessToken] expiresAt:[[delegate facebook] expirationDate]];


// Save authorization information
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[[delegate facebook] accessToken] forKey:@"FBAccessTokenKey"];
[defaults setObject:[[delegate facebook] expirationDate] forKey:@"FBExpirationDateKey"];
[defaults synchronize];

[pendingApiCallsController userDidGrantPermission]; [pendingApiCallsController userDidGrantPermission];
} }


-(void)fbDidExtendToken:(NSString *)accessToken expiresAt:(NSDate *)expiresAt {
NSLog(@"token extended");
[self storeAuthData:accessToken expiresAt:expiresAt];
}

/** /**
* Called when the user canceled the authorization dialog. * Called when the user canceled the authorization dialog.
*/ */
Expand All @@ -359,13 +358,13 @@ - (void)fbDidLogout {
/** /**
* Called when the session has expired. * Called when the session has expired.
*/ */
- (void)fbSessionInvalidated { - (void)fbSessionInvalidated {
UIAlertView *alertView = [[UIAlertView alloc] UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:@"Auth Exception" initWithTitle:@"Auth Exception"
message:@"Your session has expired." message:@"Your session has expired."
delegate:nil delegate:nil
cancelButtonTitle:@"OK" cancelButtonTitle:@"OK"
otherButtonTitles:nil, otherButtonTitles:nil,
nil]; nil];
[alertView show]; [alertView show];
[alertView release]; [alertView release];
Expand Down
24 changes: 20 additions & 4 deletions src/Facebook.h
Expand Up @@ -25,7 +25,7 @@
* and Graph APIs, and start user interface interactions (such as * and Graph APIs, and start user interface interactions (such as
* pop-ups promoting for credentials, permissions, stream posts, etc.) * pop-ups promoting for credentials, permissions, stream posts, etc.)
*/ */
@interface Facebook : NSObject<FBLoginDialogDelegate>{ @interface Facebook : NSObject<FBLoginDialogDelegate,FBRequestDelegate>{
NSString* _accessToken; NSString* _accessToken;
NSDate* _expirationDate; NSDate* _expirationDate;
id<FBSessionDelegate> _sessionDelegate; id<FBSessionDelegate> _sessionDelegate;
Expand All @@ -35,6 +35,8 @@
NSString* _appId; NSString* _appId;
NSString* _urlSchemeSuffix; NSString* _urlSchemeSuffix;
NSArray* _permissions; NSArray* _permissions;
BOOL _isExtendingAccessToken;
NSDate* _lastAccessTokenUpdate;
} }


@property(nonatomic, copy) NSString* accessToken; @property(nonatomic, copy) NSString* accessToken;
Expand All @@ -51,6 +53,12 @@


- (void)authorize:(NSArray *)permissions; - (void)authorize:(NSArray *)permissions;


- (void)extendAccessToken;

- (void)extendAccessTokenIfNeeded;

- (BOOL)shouldExtendAccessToken;

- (BOOL)handleOpenURL:(NSURL *)url; - (BOOL)handleOpenURL:(NSURL *)url;


- (void)logout; - (void)logout;
Expand Down Expand Up @@ -93,8 +101,6 @@
*/ */
@protocol FBSessionDelegate <NSObject> @protocol FBSessionDelegate <NSObject>


@optional

/** /**
* Called when the user successfully logged in. * Called when the user successfully logged in.
*/ */
Expand All @@ -105,14 +111,24 @@
*/ */
- (void)fbDidNotLogin:(BOOL)cancelled; - (void)fbDidNotLogin:(BOOL)cancelled;


/**
* Called after the access token was extended. If your application has any
* references to the previous access token (for example, if your application
* stores the previous access token in persistent storage), your application
* should overwrite the old access token with the new one in this method.
* See extendAccessToken for more details.
*/
- (void)fbDidExtendToken:(NSString*)accessToken
expiresAt:(NSDate*)expiresAt;

/** /**
* Called when the user logged out. * Called when the user logged out.
*/ */
- (void)fbDidLogout; - (void)fbDidLogout;


/** /**
* Called when the current session has expired. This might happen when: * Called when the current session has expired. This might happen when:
* - the access token expired * - the access token expired
* - the app has been disabled * - the app has been disabled
* - the user revoked the app's permissions * - the user revoked the app's permissions
* - the user changed his or her password * - the user changed his or her password
Expand Down

0 comments on commit 4aa2a66

Please sign in to comment.