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
<FBRequestDelegate,
FBSessionDelegate,
UITableViewDataSource,
UITableViewDelegate>{
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];
[navController.navigationBar setTintColor:[UIColor colorWithRed:0/255.0
green:51.0/255.0
blue:102.0/255.0
blue:102.0/255.0
alpha:1.0]];
[navController.navigationBar setBarStyle:UIBarStyleBlackTranslucent];
self.navigationController = navController;
[rootViewController release];
[navController release];

// Initialize Facebook
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.)
apiData = [[DataSet alloc] init];

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

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

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

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 {
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 = @"";
// Get the profile image
[profilePhotoImageView setImage:nil];

[[self navigationController] popToRootViewControllerAnimated:YES];
}

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

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]) {
[self showLoggedOut];
} else {
[self showLoggedIn];
}

}

- (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
/**
* Called when the user has logged in successfully.
Expand All @@ -323,16 +322,16 @@ - (void)fbDidLogin {
[self showLoggedIn];

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];
}

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

/**
* Called when the user canceled the authorization dialog.
*/
Expand All @@ -359,13 +358,13 @@ - (void)fbDidLogout {
/**
* Called when the session has expired.
*/
- (void)fbSessionInvalidated {
- (void)fbSessionInvalidated {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:@"Auth Exception"
message:@"Your session has expired."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil,
initWithTitle:@"Auth Exception"
message:@"Your session has expired."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil,
nil];
[alertView show];
[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
* pop-ups promoting for credentials, permissions, stream posts, etc.)
*/
@interface Facebook : NSObject<FBLoginDialogDelegate>{
@interface Facebook : NSObject<FBLoginDialogDelegate,FBRequestDelegate>{
NSString* _accessToken;
NSDate* _expirationDate;
id<FBSessionDelegate> _sessionDelegate;
Expand All @@ -35,6 +35,8 @@
NSString* _appId;
NSString* _urlSchemeSuffix;
NSArray* _permissions;
BOOL _isExtendingAccessToken;
NSDate* _lastAccessTokenUpdate;
}

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

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

- (void)extendAccessToken;

- (void)extendAccessTokenIfNeeded;

- (BOOL)shouldExtendAccessToken;

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

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

@optional

/**
* Called when the user successfully logged in.
*/
Expand All @@ -105,14 +111,24 @@
*/
- (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.
*/
- (void)fbDidLogout;

/**
* 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 user revoked the app's permissions
* - the user changed his or her password
Expand Down

0 comments on commit 4aa2a66

Please sign in to comment.