From ee3c9411e9bae58f7a3bdb9304a41612c9c7fa00 Mon Sep 17 00:00:00 2001 From: Aaron Douglas Date: Wed, 27 Nov 2013 09:53:15 -0600 Subject: [PATCH 1/3] #673 - Added OAuth2 token to API call to verify WP.com connectivity Updated the app delegate to include the OAuth2 token in the call out to WP.com for verification of credentials. This is NOT the ultimate solution. Auth verification should be a function of WPAccount. Removed the NSUserDefaults for the flag to indicate if the app is authenticated for WP.com - presence of OAuth2 token is the best guess at auth status upon app launch. Updated minimum WordPress install version to 3.5 per our release notes. WP.com-centric UI does not handle a revoked OAuth2 token properly (Reader for example) --- WordPress/Classes/Blog.m | 4 +++- WordPress/Classes/WordPressAppDelegate.m | 20 ++++++++------------ WordPress/WordPressApi/WordPressComApi.m | 10 ++++------ 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/WordPress/Classes/Blog.m b/WordPress/Classes/Blog.m index 01092cce7712..c2123667a0e2 100644 --- a/WordPress/Classes/Blog.m +++ b/WordPress/Classes/Blog.m @@ -15,6 +15,7 @@ #import "NSURL+IDN.h" #import "NSString+XMLExtensions.h" #import "WPError.h" +#import "WordPressComApi.h" @interface Blog (PrivateMethods) - (WPXMLRPCRequestOperation *)operationForOptionsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure; @@ -596,6 +597,7 @@ - (WPXMLRPCClient *)api { // Enable compression for wp.com only, as some self hosted have connection issues if (self.isWPcom) { [_api setDefaultHeader:@"gzip, deflate" value:@"Accept-Encoding"]; + [_api setAuthorizationHeaderWithToken:[WordPressComApi sharedApi].authToken]; } } return _api; @@ -611,7 +613,7 @@ - (WPXMLRPCRequestOperation *)operationForOptionsWithSuccess:(void (^)())success return; self.options = [NSDictionary dictionaryWithDictionary:(NSDictionary *)responseObject]; - NSString *minimumVersion = @"3.1"; + NSString *minimumVersion = @"3.5"; float version = [[self version] floatValue]; if (version < [minimumVersion floatValue]) { if (self.lastUpdateWarning == nil || [self.lastUpdateWarning floatValue] < [minimumVersion floatValue]) { diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index 1b68abc03bab..783c61fd0d8d 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -299,11 +299,10 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( [WPMobileStats initializeStats]; [[GPPSignIn sharedInstance] setClientID:[WordPressComApiCredentials googlePlusClientId]]; - if([[NSUserDefaults standardUserDefaults] objectForKey:@"wpcom_authenticated_flag"] != nil) { - NSString *tempIsAuthenticated = (NSString *)[[NSUserDefaults standardUserDefaults] objectForKey:@"wpcom_authenticated_flag"]; - if([tempIsAuthenticated isEqualToString:@"1"]) - self.isWPcomAuthenticated = YES; - } + // Temporarily set the is authenticated flag based upon if we have a WP.com OAuth2 token + // TODO :: Move this BOOL to a method on the WordPressComApi along with checkWPcomAuthentication + BOOL tempIsAuthenticated = [[WordPressComApi sharedApi] authToken].length > 0; + self.isWPcomAuthenticated = tempIsAuthenticated; // Set current directory for WordPress app NSFileManager *fileManager = [NSFileManager defaultManager]; @@ -920,12 +919,14 @@ - (void)setAppBadge { [UIApplication sharedApplication].applicationIconBadgeNumber = 0; } +// TODO :: Eliminate this check or at least move it to WordPressComApi (or WPAccount) - (void)checkWPcomAuthentication { NSString *authURL = @"https://wordpress.com/xmlrpc.php"; WPAccount *account = [WPAccount defaultWordPressComAccount]; if (account) { WPXMLRPCClient *client = [WPXMLRPCClient clientWithXMLRPCEndpoint:[NSURL URLWithString:authURL]]; + [client setAuthorizationHeaderWithToken:[[WordPressComApi sharedApi] authToken]]; [client callMethod:@"wp.getUsersBlogs" parameters:[NSArray arrayWithObjects:account.username, account.password, nil] success:^(AFHTTPRequestOperation *operation, id responseObject) { @@ -940,15 +941,10 @@ - (void)checkWPcomAuthentication { } else { isWPcomAuthenticated = NO; } - - if (isWPcomAuthenticated) - [[NSUserDefaults standardUserDefaults] setObject:@"1" forKey:@"wpcom_authenticated_flag"]; - else - [[NSUserDefaults standardUserDefaults] setObject:@"0" forKey:@"wpcom_authenticated_flag"]; } -- (void) checkIfStatsShouldRun { +- (void)checkIfStatsShouldRun { if (NO) { // Switch this to YES to debug stats/update check [self runStats]; return; @@ -1117,7 +1113,7 @@ - (void)toggleExtraDebuggingIfNeeded { } int num_blogs = [Blog countWithContext:[self managedObjectContext]]; - BOOL authed = [[[NSUserDefaults standardUserDefaults] objectForKey:@"wpcom_authenticated_flag"] boolValue]; + BOOL authed = isWPcomAuthenticated; if (num_blogs == 0 && !authed) { // When there are no blogs in the app the settings screen is unavailable. // In this case, enable extra_debugging by default to help troubleshoot any issues. diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index fba09db15f6c..0995639db415 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -105,9 +105,9 @@ + (WordPressComApi *)sharedApi { andServiceName:WordPressComApiOauthServiceName error:&error]; if (error) { - DDLogError(@"Error getting WordPress.com OAuth token: %@", error); + DDLogError(@"Error getting WordPress.com OAuth2 token: %@", error); } else { - DDLogVerbose(@"Found token for API: %@", authToken ? @"YES" : @"NO"); + DDLogVerbose(@"Found OAuth2 token for API: %@", authToken.length > 0 ? @"YES" : @"NO"); } } _sharedApi = [[self alloc] initWithBaseURL:[NSURL URLWithString:WordPressComApiClientEndpointURL] ]; @@ -172,7 +172,6 @@ - (void)signInWithUsername:(NSString *)username password:(NSString *)password su } else { WPFLog(@"Signed in as %@", self.username); [[NSUserDefaults standardUserDefaults] setObject:self.username forKey:@"wpcom_username_preference"]; - [[NSUserDefaults standardUserDefaults] setObject:@"1" forKey:@"wpcom_authenticated_flag"]; [[NSUserDefaults standardUserDefaults] synchronize]; [WordPressAppDelegate sharedWordPressApplicationDelegate].isWPcomAuthenticated = YES; [[WordPressAppDelegate sharedWordPressApplicationDelegate] registerForPushNotifications]; @@ -229,7 +228,6 @@ - (void)signOut { [[NSUserDefaults standardUserDefaults] removeObjectForKey:kApnsDeviceTokenPrefKey]; //Remove the token from Preferences, otherwise the token is never sent to the server on the next login [SFHFKeychainUtils deleteItemForUsername:self.username andServiceName:WordPressComApiOauthServiceName error:&error]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"wpcom_username_preference"]; - [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"wpcom_authenticated_flag"]; [[NSUserDefaults standardUserDefaults] synchronize]; self.authToken = nil; self.username = nil; @@ -530,9 +528,9 @@ - (void)syncPushNotificationInfo { }; WPXMLRPCRequest *tokenRequest = [api XMLRPCRequestWithMethod:@"wpcom.mobile_push_register_token" parameters:[NSArray arrayWithObjects:[self usernameForXmlrpc], [self passwordForXmlrpc], token, tokenOptions, nil]]; WPXMLRPCRequestOperation *tokenOperation = [api XMLRPCRequestOperationWithRequest:tokenRequest success:^(AFHTTPRequestOperation *operation, id responseObject) { - WPFLog(@"Registered token %@" , token); + WPFLog(@"Registered APN token %@" , token); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - WPFLog(@"Couldn't register token: %@", [error localizedDescription]); + WPFLog(@"Couldn't register APN token: %@", [error localizedDescription]); }]; [operations addObject:tokenOperation]; From 7ef613a38a9bd4ff0fd5953ab1d5a49126a2fd46 Mon Sep 17 00:00:00 2001 From: Aaron Douglas Date: Wed, 27 Nov 2013 10:34:19 -0600 Subject: [PATCH 2/3] #673 - Wipe OAuth2 token if check upon launch fails Should probably be centralized so that any time an API request fails with a fault we tell the user to try logging in again. Way too many changes for that to be safe in this release. --- WordPress/Classes/WordPressAppDelegate.m | 5 ++++- WordPress/WordPressApi/WordPressComApi.h | 2 ++ WordPress/WordPressApi/WordPressComApi.m | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index 783c61fd0d8d..6cfaf5965547 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -933,9 +933,12 @@ - (void)checkWPcomAuthentication { isWPcomAuthenticated = YES; DDLogInfo(@"Logged in to WordPress.com as %@", account.username); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if ([error.domain isEqualToString:@"XMLRPC"] && error.code == 403) { + if ([error.domain isEqualToString:@"WPXMLRPCFaultError"] || + ([error.domain isEqualToString:@"XMLRPC"] && error.code == 403)) { isWPcomAuthenticated = NO; + [[WordPressComApi sharedApi] invalidateOAuth2Token]; } + DDLogError(@"Error authenticating %@ with WordPress.com: %@", account.username, [error description]); }]; } else { diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 3c04dc66cd93..6834adfe5cf7 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -49,6 +49,8 @@ extern NSString *const WordPressComApiErrorMessageKey; - (void)signInWithToken:(NSString *)token DEPRECATED_ATTRIBUTE; - (void)signOut; - (BOOL)hasCredentials; +// Wipe the OAuth2 token +- (void)invalidateOAuth2Token; - (void)validateWPComAccountWithEmail:(NSString *)email andUsername:(NSString *)username andPassword:(NSString *)password success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure; - (void)createWPComAccountWithEmail:(NSString *)email andUsername:(NSString *)username andPassword:(NSString *)password success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure; - (void)validateWPComBlogWithUrl:(NSString *)blogUrl andBlogTitle:(NSString *)blogTitle andLanguageId:(NSNumber *)languageId success:(void (^)(id))success failure:(void (^)(NSError *))failure; diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index 0995639db415..00de390aa0b0 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -244,7 +244,11 @@ - (void)signOut { } - (BOOL)hasCredentials { - return _authToken != nil; + return _authToken.length > 0; +} + +- (void)invalidateOAuth2Token { + [self setAuthToken:nil]; } - (void)validateWPComAccountWithEmail:(NSString *)email andUsername:(NSString *)username andPassword:(NSString *)password success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure From 025fafe543d97a8356f7b2cf9c38d7f2e70308b4 Mon Sep 17 00:00:00 2001 From: Aaron Douglas Date: Wed, 27 Nov 2013 12:18:43 -0600 Subject: [PATCH 3/3] #673 - Turn WordPressComApi authToken into a real property --- WordPress/WordPressApi/WordPressComApi.h | 2 +- WordPress/WordPressApi/WordPressComApi.m | 12 +++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 6834adfe5cf7..c7328fa99c68 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -37,6 +37,7 @@ extern NSString *const WordPressComApiErrorMessageKey; @interface WordPressComApi : AFHTTPClient @property (nonatomic,readonly,strong) NSString *username; @property (nonatomic,readonly,strong) NSString *password; +@property (nonatomic, readonly, strong) NSString *authToken; + (WordPressComApi *)sharedApi; @@ -131,7 +132,6 @@ extern NSString *const WordPressComApiErrorMessageKey; /// @name OAuth info ///----------------- -- (NSString *)authToken; + (NSString *)WordPressAppId; + (NSString *)WordPressAppSecret; diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index 00de390aa0b0..a65d3983ebba 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -73,15 +73,13 @@ - (NSError *)error { @interface WordPressComApi () @property (readwrite, nonatomic, strong) NSString *username; @property (readwrite, nonatomic, strong) NSString *password; -@property (nonatomic, strong) NSString *authToken; +@property (readwrite, nonatomic, strong) NSString *authToken; - (void)clearWpcomCookies; @end -@implementation WordPressComApi { - NSString *_authToken; -} +@implementation WordPressComApi + (WordPressComApi *)sharedApi { static WordPressComApi *_sharedApi = nil; @@ -244,7 +242,7 @@ - (void)signOut { } - (BOOL)hasCredentials { - return _authToken.length > 0; + return self.authToken.length > 0; } - (void)invalidateOAuth2Token { @@ -734,10 +732,6 @@ - (NSString *)passwordForXmlrpc { #pragma mark - Oauth methods -- (NSString *)authToken { - return _authToken; -} - - (void)setAuthToken:(NSString *)authToken { _authToken = authToken; NSError *error;