diff --git a/Source/Framework/MPOAuthAPI.h b/Source/Framework/MPOAuthAPI.h index c6cf2ba..5fd8baf 100644 --- a/Source/Framework/MPOAuthAPI.h +++ b/Source/Framework/MPOAuthAPI.h @@ -43,6 +43,7 @@ typedef enum { @end @class MPOAuthAuthenticationMethod; +@class MPOAuthAPIRequestLoader; @interface MPOAuthAPI : NSObject { @private @@ -69,15 +70,15 @@ typedef enum { - (id)initWithCredentials:(NSDictionary *)inCredentials authenticationURL:(NSURL *)inAuthURL andBaseURL:(NSURL *)inBaseURL autoStart:(BOOL)aFlag; - (id)initWithCredentials:(NSDictionary *)inCredentials withConfiguration:(NSDictionary *)inConfiguration autoStart:(BOOL)aFlag; -- (void)authenticate; +- (void)beginAuthentication; - (BOOL)isAuthenticated; -- (void)performMethod:(NSString *)inMethod withTarget:(id)inTarget andAction:(SEL)inAction; -- (void)performMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction; -- (void)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction; -- (void)performPOSTMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction; -- (void)performPOSTMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction; -- (void)performURLRequest:(NSURLRequest *)inRequest withTarget:(id)inTarget andAction:(SEL)inAction; +- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod withTarget:(id)inTarget andAction:(SEL)inAction; +- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction; +- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction; +- (MPOAuthAPIRequestLoader*)performPOSTMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction; +- (MPOAuthAPIRequestLoader*)performPOSTMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction; +- (MPOAuthAPIRequestLoader*)performURLRequest:(NSURLRequest *)inRequest withTarget:(id)inTarget andAction:(SEL)inAction; - (NSData *)dataForMethod:(NSString *)inMethod; - (NSData *)dataForMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters; diff --git a/Source/Framework/MPOAuthAPI.m b/Source/Framework/MPOAuthAPI.m index 6369959..0c6c7c0 100644 --- a/Source/Framework/MPOAuthAPI.m +++ b/Source/Framework/MPOAuthAPI.m @@ -39,7 +39,7 @@ @interface MPOAuthAPI () @property (nonatomic, readwrite, retain) NSMutableArray *activeLoaders; @property (nonatomic, readwrite, assign) MPOAuthAuthenticationState authenticationState; -- (void)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction usingHTTPMethod:(NSString *)inHTTPMethod; +- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction usingHTTPMethod:(NSString *)inHTTPMethod; @end @implementation MPOAuthAPI @@ -53,7 +53,7 @@ - (id)initWithCredentials:(NSDictionary *)inCredentials authenticationURL:(NSURL } - (id)initWithCredentials:(NSDictionary *)inCredentials authenticationURL:(NSURL *)inAuthURL andBaseURL:(NSURL *)inBaseURL autoStart:(BOOL)aFlag { - if (self = [super init]) { + if ((self = [super init])) { self.authenticationURL = inAuthURL; self.baseURL = inBaseURL; self.authenticationState = MPOAuthAuthenticationStateUnauthenticated; @@ -64,14 +64,14 @@ - (id)initWithCredentials:(NSDictionary *)inCredentials authenticationURL:(NSURL activeLoaders_ = [[NSMutableArray alloc] initWithCapacity:10]; if (aFlag) { - [self authenticate]; + [self beginAuthentication]; } } return self; } - (id)initWithCredentials:(NSDictionary *)inCredentials withConfiguration:(NSDictionary *)inConfiguration autoStart:(BOOL)aFlag { - if (self = [super init]) { + if ((self = [super init])) { self.authenticationURL = [inConfiguration valueForKey:MPOAuthAuthenticationURLKey]; self.baseURL = [inConfiguration valueForKey:MPOAuthBaseURLKey]; self.authenticationState = MPOAuthAuthenticationStateUnauthenticated; @@ -82,7 +82,7 @@ - (id)initWithCredentials:(NSDictionary *)inCredentials withConfiguration:(NSDic activeLoaders_ = [[NSMutableArray alloc] initWithCapacity:10]; if (aFlag) { - [self authenticate]; + [self beginAuthentication]; } } return self; @@ -130,9 +130,9 @@ - (void)setSignatureScheme:(MPOAuthSignatureScheme)inScheme { #pragma mark - -- (void)authenticate { +- (void)beginAuthentication { NSAssert(credentials_.consumerKey, @"A Consumer Key is required for use of OAuth."); - [self.authenticationMethod authenticate]; + [self.authenticationMethod beginAuthentication]; } - (BOOL)isAuthenticated { @@ -141,27 +141,27 @@ - (BOOL)isAuthenticated { #pragma mark - -- (void)performMethod:(NSString *)inMethod withTarget:(id)inTarget andAction:(SEL)inAction { - [self performMethod:inMethod atURL:self.baseURL withParameters:nil withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"]; +- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod withTarget:(id)inTarget andAction:(SEL)inAction { + return [self performMethod:inMethod atURL:self.baseURL withParameters:nil withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"]; } -- (void)performMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction { - [self performMethod:inMethod atURL:self.baseURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"]; +- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction { + return [self performMethod:inMethod atURL:self.baseURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"]; } -- (void)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction { - [self performMethod:inMethod atURL:inURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"]; +- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction { + return [self performMethod:inMethod atURL:inURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"GET"]; } -- (void)performPOSTMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction { - [self performPOSTMethod:inMethod atURL:self.baseURL withParameters:inParameters withTarget:inTarget andAction:inAction]; +- (MPOAuthAPIRequestLoader*)performPOSTMethod:(NSString *)inMethod withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction { + return [self performPOSTMethod:inMethod atURL:self.baseURL withParameters:inParameters withTarget:inTarget andAction:inAction]; } -- (void)performPOSTMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction { - [self performMethod:inMethod atURL:inURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"POST"]; +- (MPOAuthAPIRequestLoader*)performPOSTMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction { + return [self performMethod:inMethod atURL:inURL withParameters:inParameters withTarget:inTarget andAction:inAction usingHTTPMethod:@"POST"]; } -- (void)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction usingHTTPMethod:(NSString *)inHTTPMethod { +- (MPOAuthAPIRequestLoader*)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:(NSArray *)inParameters withTarget:(id)inTarget andAction:(SEL)inAction usingHTTPMethod:(NSString *)inHTTPMethod { if (!inMethod && ![inURL path] && ![inURL query]) { [NSException raise:@"MPOAuthNilMethodRequestException" format:@"Nil was passed as the method to be performed on %@", inURL]; } @@ -180,9 +180,11 @@ - (void)performMethod:(NSString *)inMethod atURL:(NSURL *)inURL withParameters:( [loader release]; [aRequest release]; + + return loader; } -- (void)performURLRequest:(NSURLRequest *)inRequest withTarget:(id)inTarget andAction:(SEL)inAction { +- (MPOAuthAPIRequestLoader*)performURLRequest:(NSURLRequest *)inRequest withTarget:(id)inTarget andAction:(SEL)inAction { if (!inRequest && ![[inRequest URL] path] && ![[inRequest URL] query]) { [NSException raise:@"MPOAuthNilMethodRequestException" format:@"Nil was passed as the method to be performed on %@", inRequest]; } @@ -199,6 +201,8 @@ - (void)performURLRequest:(NSURLRequest *)inRequest withTarget:(id)inTarget andA [loader release]; [aRequest release]; + + return loader; } - (NSData *)dataForMethod:(NSString *)inMethod { diff --git a/Source/Framework/MPOAuthAPIRequestLoader.h b/Source/Framework/MPOAuthAPIRequestLoader.h index affe1a2..a11d1b1 100644 --- a/Source/Framework/MPOAuthAPIRequestLoader.h +++ b/Source/Framework/MPOAuthAPIRequestLoader.h @@ -18,12 +18,14 @@ extern NSString * const MPOAuthNotificationErrorHasOccurred; @protocol MPOAuthCredentialStore; @protocol MPOAuthParameterFactory; +@class MPOAuthConnection; @class MPOAuthURLRequest; @class MPOAuthURLResponse; @class MPOAuthCredentialConcreteStore; @interface MPOAuthAPIRequestLoader : NSObject { MPOAuthCredentialConcreteStore *_credentials; + MPOAuthConnection *_connection; MPOAuthURLRequest *_oauthRequest; MPOAuthURLResponse *_oauthResponse; NSMutableData *_dataBuffer; @@ -46,5 +48,7 @@ extern NSString * const MPOAuthNotificationErrorHasOccurred; - (void)loadSynchronously:(BOOL)inSynchronous; +- (void)cancel; + @end diff --git a/Source/Framework/MPOAuthAPIRequestLoader.m b/Source/Framework/MPOAuthAPIRequestLoader.m index 7d3637b..d2d5027 100644 --- a/Source/Framework/MPOAuthAPIRequestLoader.m +++ b/Source/Framework/MPOAuthAPIRequestLoader.m @@ -34,7 +34,7 @@ @interface MPOAuthAPIRequestLoader () @property (nonatomic, readwrite, retain) NSData *data; @property (nonatomic, readwrite, retain) NSString *responseString; -- (void)_interrogateResponseForOAuthData; +- (BOOL)_interrogateResponseForOAuthData; @end @protocol MPOAuthAPIInternalClient; @@ -46,7 +46,7 @@ - (id)initWithURL:(NSURL *)inURL { } - (id)initWithRequest:(MPOAuthURLRequest *)inRequest { - if (self = [super init]) { + if ((self = [super init])) { self.oauthRequest = inRequest; _dataBuffer = [[NSMutableData alloc] init]; } @@ -94,7 +94,7 @@ - (void)loadSynchronously:(BOOL)inSynchronous { NSAssert(_credentials.consumerKey, @"Unable to load, credentials contain no consumer key"); if (!inSynchronous) { - [MPOAuthConnection connectionWithRequest:self.oauthRequest delegate:self credentials:self.credentials]; + _connection = [MPOAuthConnection connectionWithRequest:self.oauthRequest delegate:self credentials:self.credentials]; } else { MPOAuthURLResponse *theOAuthResponse = nil; self.data = [MPOAuthConnection sendSynchronousRequest:self.oauthRequest usingCredentials:self.credentials returningResponse:&theOAuthResponse error:nil]; @@ -103,9 +103,17 @@ - (void)loadSynchronously:(BOOL)inSynchronous { } } +- (void)cancel { + if ( _connection ) { + [_connection cancel]; + _connection = nil; + } +} + #pragma mark - - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + _connection = nil; MPLog(@"%p: [%@ %@] %@, %@", self, NSStringFromClass([self class]), NSStringFromSelector(_cmd), connection, error); if ([_target respondsToSelector:@selector(loader:didFailWithError:)]) { [_target performSelector: @selector(loader:didFailWithError:) withObject: self withObject: error]; @@ -130,9 +138,10 @@ - (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSUR } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { + _connection = nil; [self _interrogateResponseForOAuthData]; - if (_action) { + if ( _action ) { if ([_target conformsToProtocol:@protocol(MPOAuthAPIInternalClient)]) { [_target performSelector:_action withObject:self withObject:self.data]; } else { @@ -143,78 +152,76 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)connection { #pragma mark - -- (void)_interrogateResponseForOAuthData { +- (BOOL)_interrogateResponseForOAuthData { NSString *response = self.responseString; NSDictionary *foundParameters = nil; NSInteger status = [(NSHTTPURLResponse *)[self.oauthResponse urlResponse] statusCode]; - if ([response length] > 5 && [[response substringToIndex:5] isEqualToString:@"oauth"]) { - foundParameters = [MPURLRequestParameter parameterDictionaryFromString:response]; - self.oauthResponse.oauthParameters = foundParameters; - - if (status == 401 || [foundParameters objectForKey:@"oauth_problem"]) { - NSString *aParameterValue = nil; - MPLog(@"oauthProblem = %@", foundParameters); - - if ([foundParameters count] && (aParameterValue = [foundParameters objectForKey:@"oauth_problem"])) { - if ([aParameterValue isEqualToString:@"token_rejected"]) { - if (self.credentials.requestToken && !self.credentials.accessToken) { - [_credentials setRequestToken:nil]; - [_credentials setRequestTokenSecret:nil]; - - [[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationRequestTokenRejected - object:nil - userInfo:foundParameters]; - } else if (self.credentials.accessToken && !self.credentials.requestToken) { - // your access token may be invalid due to a number of reasons so it's up to the - // user to decide whether or not to remove them - [[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationAccessTokenRejected - object:nil - userInfo:foundParameters]; - - } - } - - // something's messed up, so throw an error - [[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationErrorHasOccurred - object:nil - userInfo:foundParameters]; - } - } else if ([foundParameters objectForKey:@"oauth_token"]) { - NSString *aParameterValue = nil; - MPLog(@"foundParameters = %@", foundParameters); - - if ([foundParameters count] && (aParameterValue = [foundParameters objectForKey:@"oauth_token"])) { - if (!self.credentials.requestToken && !self.credentials.accessToken) { - [_credentials setRequestToken:aParameterValue]; - [_credentials setRequestTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]]; - - [[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationRequestTokenReceived - object:nil - userInfo:foundParameters]; - - } else if (!self.credentials.accessToken && self.credentials.requestToken) { - [_credentials setRequestToken:nil]; - [_credentials setRequestTokenSecret:nil]; - [_credentials setAccessToken:aParameterValue]; - [_credentials setAccessTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]]; - - [[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationAccessTokenReceived - object:nil - userInfo:foundParameters]; - - } else if (self.credentials.accessToken && !self.credentials.requestToken) { - // replace the current token - [_credentials setAccessToken:aParameterValue]; - [_credentials setAccessTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]]; - - [[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationAccessTokenRefreshed - object:nil - userInfo:foundParameters]; - } - } - } + if ([response length] > 5 && [[response substringToIndex:5] isEqualToString:@"oauth"]) { + foundParameters = [MPURLRequestParameter parameterDictionaryFromString:response]; + self.oauthResponse.oauthParameters = foundParameters; + } + + if ( status == 401 || ![foundParameters count] || [foundParameters objectForKey:@"oauth_problem"] ) { + NSString *aParameterValue = nil; + MPLog(@"oauthProblem = %@", foundParameters); + + if ( status == 401 || ([foundParameters count] && (aParameterValue = [foundParameters objectForKey:@"oauth_problem"])) ) { + if ( !aParameterValue || [aParameterValue isEqualToString:@"token_rejected"]) { + [_credentials setRequestToken:nil]; + [_credentials setRequestTokenSecret:nil]; + + [[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationRequestTokenRejected + object:nil + userInfo:foundParameters]; + } + return NO; + } + + // something's messed up, so throw an error + [[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationErrorHasOccurred + object:nil + userInfo:foundParameters]; + return NO; + } + + if ( foundParameters && [foundParameters objectForKey:@"oauth_token"]) { + NSString *aParameterValue = nil; + MPLog(@"foundParameters = %@", foundParameters); + + if ([foundParameters count] && (aParameterValue = [foundParameters objectForKey:@"oauth_token"])) { + if (!self.credentials.requestToken && !self.credentials.accessToken) { + [_credentials setRequestToken:aParameterValue]; + [_credentials setRequestTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]]; + + [[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationRequestTokenReceived + object:nil + userInfo:foundParameters]; + + } else if (!self.credentials.accessToken && self.credentials.requestToken) { + [_credentials setRequestToken:nil]; + [_credentials setRequestTokenSecret:nil]; + [_credentials setAccessToken:aParameterValue]; + [_credentials setAccessTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]]; + + [[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationAccessTokenReceived + object:nil + userInfo:foundParameters]; + + } else if (self.credentials.accessToken && !self.credentials.requestToken) { + // replace the current token + [_credentials setAccessToken:aParameterValue]; + [_credentials setAccessTokenSecret:[foundParameters objectForKey:@"oauth_token_secret"]]; + + [[NSNotificationCenter defaultCenter] postNotificationName:MPOAuthNotificationAccessTokenRefreshed + object:nil + userInfo:foundParameters]; + } + return YES; + } } + + return NO; } @end diff --git a/Source/Framework/MPOAuthAuthenticationMethod.h b/Source/Framework/MPOAuthAuthenticationMethod.h index f3dbd39..eb9032d 100644 --- a/Source/Framework/MPOAuthAuthenticationMethod.h +++ b/Source/Framework/MPOAuthAuthenticationMethod.h @@ -10,6 +10,12 @@ extern NSString * const MPOAuthAccessTokenURLKey; +extern NSString * const MPOAuthAuthenticationErrorDomain; + +enum { + MPOAuthAuthenticationErrorUnknown +}; + @class MPOAuthAPI; @interface MPOAuthAuthenticationMethod : NSObject { @@ -23,7 +29,7 @@ extern NSString * const MPOAuthAccessTokenURLKey; - (id)initWithAPI:(MPOAuthAPI *)inAPI forURL:(NSURL *)inURL; - (id)initWithAPI:(MPOAuthAPI *)inAPI forURL:(NSURL *)inURL withConfiguration:(NSDictionary *)inConfig; -- (void)authenticate; +- (void)beginAuthentication; - (void)setTokenRefreshInterval:(NSTimeInterval)inTimeInterval; - (void)refreshAccessToken; diff --git a/Source/Framework/MPOAuthAuthenticationMethod.m b/Source/Framework/MPOAuthAuthenticationMethod.m index 12b300c..0f114ef 100644 --- a/Source/Framework/MPOAuthAuthenticationMethod.m +++ b/Source/Framework/MPOAuthAuthenticationMethod.m @@ -15,6 +15,8 @@ NSString * const MPOAuthAccessTokenURLKey = @"MPOAuthAccessTokenURL"; +NSString * const MPOAuthAuthenticationErrorDomain = @"MPOAuthAuthenticationErrorDomain"; + @interface MPOAuthAuthenticationMethod () @property (nonatomic, readwrite, retain) NSTimer *refreshTimer; @@ -93,7 +95,7 @@ + (Class)_authorizationMethodClassForURL:(NSURL *)inBaseURL withConfiguration:(N #pragma mark - -- (void)authenticate { +- (void)beginAuthentication { [NSException raise:@"Not Implemented" format:@"All subclasses of MPOAuthAuthenticationMethod are required to implement -authenticate"]; } diff --git a/Source/Framework/MPOAuthAuthenticationMethodAuthExchange.m b/Source/Framework/MPOAuthAuthenticationMethodAuthExchange.m index eb2b592..b7dce2f 100644 --- a/Source/Framework/MPOAuthAuthenticationMethodAuthExchange.m +++ b/Source/Framework/MPOAuthAuthenticationMethodAuthExchange.m @@ -23,13 +23,13 @@ @interface MPOAuthAPI () @implementation MPOAuthAuthenticationMethodAuthExchange - (id)initWithAPI:(MPOAuthAPI *)inAPI forURL:(NSURL *)inURL withConfiguration:(NSDictionary *)inConfig { - if (self = [super initWithAPI:inAPI forURL:inURL withConfiguration:inConfig]) { + if ((self = [super initWithAPI:inAPI forURL:inURL withConfiguration:inConfig])) { self.oauthGetAccessTokenURL = [NSURL URLWithString:[inConfig objectForKey:MPOAuthAccessTokenURLKey]]; } return self; } -- (void)authenticate { +- (void)beginAuthentication { id credentials = [self.oauthAPI credentials]; if (!credentials.accessToken && !credentials.accessTokenSecret) { @@ -42,6 +42,7 @@ - (void)authenticate { MPURLRequestParameter *usernameParameter = [[MPURLRequestParameter alloc] initWithName:@"fs_username" andValue:username]; MPURLRequestParameter *passwordParameter = [[MPURLRequestParameter alloc] initWithName:@"fs_password" andValue:password]; + [self.oauthAPI setAuthenticationState:MPOAuthAuthenticationStateAuthenticating]; [self.oauthAPI performPOSTMethod:nil atURL:self.oauthGetAccessTokenURL withParameters:[NSArray arrayWithObjects:usernameParameter, passwordParameter, nil] @@ -52,10 +53,12 @@ - (void)authenticate { NSDate *tokenExpiryDate = [NSDate dateWithTimeIntervalSinceReferenceDate:expiryDateInterval]; if ([tokenExpiryDate compare:[NSDate date]] == NSOrderedAscending) { + [self.oauthAPI setAuthenticationState:MPOAuthAuthenticationStateAuthenticating]; [self refreshAccessToken]; } - } - + } else { + [self.oauthAPI setAuthenticationState:MPOAuthAuthenticationStateAuthenticated]; + } } - (void)_performedLoad:(MPOAuthAPIRequestLoader *)inLoader receivingData:(NSData *)inData { diff --git a/Source/Framework/MPOAuthAuthenticationMethodOAuth.h b/Source/Framework/MPOAuthAuthenticationMethodOAuth.h index 088adad..2159af4 100644 --- a/Source/Framework/MPOAuthAuthenticationMethodOAuth.h +++ b/Source/Framework/MPOAuthAuthenticationMethodOAuth.h @@ -33,7 +33,7 @@ extern NSString * const MPOAuthNotificationRequestTokenRejected; @property (nonatomic, readwrite, retain) NSURL *oauthRequestTokenURL; @property (nonatomic, readwrite, retain) NSURL *oauthAuthorizeTokenURL; -- (void)authenticate; +- (void)beginAuthentication; @end diff --git a/Source/Framework/MPOAuthAuthenticationMethodOAuth.m b/Source/Framework/MPOAuthAuthenticationMethodOAuth.m index faebdb3..d05c9a0 100644 --- a/Source/Framework/MPOAuthAuthenticationMethodOAuth.m +++ b/Source/Framework/MPOAuthAuthenticationMethodOAuth.m @@ -44,7 +44,7 @@ - (void)_authenticationRequestForAccessToken; @implementation MPOAuthAuthenticationMethodOAuth - (id)initWithAPI:(MPOAuthAPI *)inAPI forURL:(NSURL *)inURL withConfiguration:(NSDictionary *)inConfig { - if (self = [super initWithAPI:inAPI forURL:inURL withConfiguration:inConfig]) { + if ((self = [super initWithAPI:inAPI forURL:inURL withConfiguration:inConfig])) { NSAssert( [inConfig count] >= 3, @"Incorrect number of oauth authorization methods"); self.oauthRequestTokenURL = [NSURL URLWithString:[inConfig objectForKey:MPOAuthRequestTokenURLKey]]; @@ -53,7 +53,7 @@ - (id)initWithAPI:(MPOAuthAPI *)inAPI forURL:(NSURL *)inURL withConfiguration:(N [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_requestTokenReceived:) name:MPOAuthNotificationRequestTokenReceived object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_requestTokenRejected:) name:MPOAuthNotificationRequestTokenRejected object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_accessTokenReceived:) name:MPOAuthNotificationAccessTokenReceived object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_accessTokenReceived:) name:MPOAuthNotificationAccessTokenReceived object:nil]; } return self; } @@ -74,21 +74,26 @@ - (oneway void)dealloc { #pragma mark - -- (void)authenticate { +- (void)beginAuthentication { id credentials = [self.oauthAPI credentials]; if (!credentials.accessToken && !credentials.requestToken) { + [self.oauthAPI setAuthenticationState:MPOAuthAuthenticationStateAuthenticating]; [self _authenticationRequestForRequestToken]; } else if (!credentials.accessToken) { + [self.oauthAPI setAuthenticationState:MPOAuthAuthenticationStateAuthenticating]; [self _authenticationRequestForAccessToken]; } else if (credentials.accessToken && [[NSUserDefaults standardUserDefaults] objectForKey:MPOAuthTokenRefreshDateDefaultsKey]) { NSTimeInterval expiryDateInterval = [[NSUserDefaults standardUserDefaults] doubleForKey:MPOAuthTokenRefreshDateDefaultsKey]; NSDate *tokenExpiryDate = [NSDate dateWithTimeIntervalSinceReferenceDate:expiryDateInterval]; if ([tokenExpiryDate compare:[NSDate date]] == NSOrderedAscending) { + [self.oauthAPI setAuthenticationState:MPOAuthAuthenticationStateAuthenticating]; [self refreshAccessToken]; } - } + } else { + [self.oauthAPI setAuthenticationState:MPOAuthAuthenticationStateAuthenticated]; + } } - (void)_authenticationRequestForRequestToken { @@ -112,6 +117,15 @@ - (void)_authenticationRequestForRequestToken { - (void)_authenticationRequestForRequestTokenSuccessfulLoad:(MPOAuthAPIRequestLoader *)inLoader withData:(NSData *)inData { NSDictionary *oauthResponseParameters = inLoader.oauthResponse.oauthParameters; + if ( ![oauthResponseParameters objectForKey:@"oauth_token"] ) { + if ([self.delegate respondsToSelector:@selector(authenticationDidFailWithError:)]) { + [self.delegate authenticationDidFailWithError:[NSError errorWithDomain:MPOAuthAuthenticationErrorDomain + code:MPOAuthAuthenticationErrorUnknown + userInfo:nil]]; + } + return; + } + NSString *xoauthRequestAuthURL = [oauthResponseParameters objectForKey:@"xoauth_request_auth_url"]; // a common custom extension, used by Yahoo! NSURL *userAuthURL = xoauthRequestAuthURL ? [NSURL URLWithString:xoauthRequestAuthURL] : self.oauthAuthorizeTokenURL; NSURL *callbackURL = nil; @@ -180,6 +194,7 @@ - (void)_requestTokenReceived:(NSNotification *)inNotification { - (void)_requestTokenRejected:(NSNotification *)inNotification { [self.oauthAPI removeCredentialNamed:MPOAuthCredentialRequestTokenKey]; [self.oauthAPI removeCredentialNamed:MPOAuthCredentialRequestTokenSecretKey]; + [self beginAuthentication]; } - (void)_accessTokenReceived:(NSNotification *)inNotification { diff --git a/Source/Framework/MPOAuthAuthenticationMethodXAuth.m b/Source/Framework/MPOAuthAuthenticationMethodXAuth.m index 81e23cc..2af619a 100644 --- a/Source/Framework/MPOAuthAuthenticationMethodXAuth.m +++ b/Source/Framework/MPOAuthAuthenticationMethodXAuth.m @@ -17,13 +17,13 @@ @interface MPOAuthAPI () @implementation MPOAuthAuthenticationMethodXAuth - (id)initWithAPI:(MPOAuthAPI *)inAPI forURL:(NSURL *)inURL withConfiguration:(NSDictionary *)inConfig { - if (self = [super initWithAPI:inAPI forURL:inURL withConfiguration:inConfig]) { + if ((self = [super initWithAPI:inAPI forURL:inURL withConfiguration:inConfig])) { self.oauthGetAccessTokenURL = [NSURL URLWithString:[inConfig objectForKey:MPOAuthAccessTokenURLKey]]; } return self; } -- (void)authenticate { +- (void)beginAuthentication { id credentials = [self.oauthAPI credentials]; if (!credentials.accessToken && !credentials.accessTokenSecret) { @@ -37,19 +37,24 @@ - (void)authenticate { MPURLRequestParameter *passwordParameter = [[MPURLRequestParameter alloc] initWithName:@"x_auth_password" andValue:password]; MPURLRequestParameter *clientModeParameter = [[MPURLRequestParameter alloc] initWithName:@"x_auth_mode" andValue:@"client_auth"]; + [self.oauthAPI setAuthenticationState:MPOAuthAuthenticationStateAuthenticating]; [self.oauthAPI performPOSTMethod:nil atURL:self.oauthGetAccessTokenURL withParameters:[NSArray arrayWithObjects:usernameParameter, passwordParameter, clientModeParameter, nil] withTarget:self andAction:nil]; + } else if (credentials.accessToken && credentials.accessTokenSecret) { NSTimeInterval expiryDateInterval = [[NSUserDefaults standardUserDefaults] doubleForKey:MPOAuthTokenRefreshDateDefaultsKey]; NSDate *tokenExpiryDate = [NSDate dateWithTimeIntervalSinceReferenceDate:expiryDateInterval]; if ([tokenExpiryDate compare:[NSDate date]] == NSOrderedAscending) { + [self.oauthAPI setAuthenticationState:MPOAuthAuthenticationStateAuthenticating]; [self refreshAccessToken]; } - } + } else { + [self.oauthAPI setAuthenticationState:MPOAuthAuthenticationStateAuthenticated]; + } } diff --git a/Source/Framework/MPOAuthConnection.m b/Source/Framework/MPOAuthConnection.m index 3aeb0b3..4e02c9a 100644 --- a/Source/Framework/MPOAuthConnection.m +++ b/Source/Framework/MPOAuthConnection.m @@ -39,7 +39,7 @@ + (NSData *)sendSynchronousRequest:(MPOAuthURLRequest *)inRequest usingCredentia - (id)initWithRequest:(MPOAuthURLRequest *)inRequest delegate:(id)inDelegate credentials:(NSObject *)inCredentials { [inRequest addParameters:[inCredentials oauthParameters]]; NSURLRequest *urlRequest = [inRequest urlRequestSignedWithSecret:[inCredentials signingKey] usingMethod:[inCredentials signatureMethod]]; - if (self = [super initWithRequest:urlRequest delegate:inDelegate]) { + if ((self = [super initWithRequest:urlRequest delegate:inDelegate])) { _credentials = [inCredentials retain]; } return self; diff --git a/Source/Framework/MPOAuthURLRequest.h b/Source/Framework/MPOAuthURLRequest.h index 7e14a04..969e586 100644 --- a/Source/Framework/MPOAuthURLRequest.h +++ b/Source/Framework/MPOAuthURLRequest.h @@ -29,4 +29,6 @@ - (NSURLRequest *)urlRequestSignedWithSecret:(NSString *)inSecret usingMethod:(NSString *)inScheme; ++ (NSString *)authorizationHeaderValueFromParameterString:(NSString*)parameterString; + @end diff --git a/Source/Framework/MPOAuthURLRequest.m b/Source/Framework/MPOAuthURLRequest.m index 4831df3..37a71d7 100644 --- a/Source/Framework/MPOAuthURLRequest.m +++ b/Source/Framework/MPOAuthURLRequest.m @@ -20,7 +20,7 @@ @interface MPOAuthURLRequest () @implementation MPOAuthURLRequest - (id)initWithURL:(NSURL *)inURL andParameters:(NSArray *)inParameters { - if (self = [super init]) { + if ((self = [super init])) { self.url = inURL; _parameters = inParameters ? [inParameters mutableCopy] : [[NSMutableArray alloc] initWithCapacity:10]; self.HTTPMethod = @"GET"; @@ -29,7 +29,7 @@ - (id)initWithURL:(NSURL *)inURL andParameters:(NSArray *)inParameters { } - (id)initWithURLRequest:(NSURLRequest *)inRequest { - if (self = [super init]) { + if ((self = [super init])) { self.url = [[inRequest URL] urlByRemovingQuery]; self.parameters = [[[MPURLRequestParameter parametersFromString:[[inRequest URL] query]] mutableCopy] autorelease]; self.HTTPMethod = [inRequest HTTPMethod]; @@ -60,7 +60,7 @@ - (NSArray *)nonOAuthParameters { return [self.parameters filteredArrayUsingPredicate:filterPredicate]; } -- (NSString *)authorizationHeaderValueFromParameterString:(NSString *)parameterString { ++ (NSString *)authorizationHeaderValueFromParameterString:(NSString *)parameterString { NSDictionary *paramsDict = [MPURLRequestParameter parameterDictionaryFromString:parameterString]; NSString *signature = [[paramsDict objectForKey:@"oauth_signature"] stringByAddingURIPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSString *nonce = [[paramsDict objectForKey:@"oauth_nonce"] stringByAddingURIPercentEscapesUsingEncoding:NSUTF8StringEncoding]; @@ -100,7 +100,7 @@ - (NSURLRequest *)urlRequestSignedWithSecret:(NSString *)inSecret usingMethod:( } else if ([[self HTTPMethod] isEqualToString:@"POST"]) { NSArray *nonOauthParameters = [self nonOAuthParameters]; urlString = [self.url absoluteString]; - [aRequest setValue: [self authorizationHeaderValueFromParameterString:parameterString] forHTTPHeaderField:@"Authorization"]; + [aRequest setValue: [MPOAuthURLRequest authorizationHeaderValueFromParameterString:parameterString] forHTTPHeaderField:@"Authorization"]; if ([nonOauthParameters count] && [aRequest HTTPBody]) { [NSException raise:@"MalformedHTTPPOSTMethodException" format:@"The request has both an HTTP Body and additional parameters. This is not supported."]; diff --git a/Source/Mobile Test App/RootViewController.m b/Source/Mobile Test App/RootViewController.m index b31c802..13c1c78 100644 --- a/Source/Mobile Test App/RootViewController.m +++ b/Source/Mobile Test App/RootViewController.m @@ -50,7 +50,7 @@ - (void)viewDidAppear:(BOOL)animated { [(MPOAuthAuthenticationMethodOAuth *)[_oauthAPI authenticationMethod] setDelegate:(id )[UIApplication sharedApplication].delegate]; } } else { - [_oauthAPI authenticate]; + [_oauthAPI beginAuthentication]; } } @@ -95,7 +95,7 @@ - (void)clearCredentials { - (void)reauthenticate { [self.navigationItem setPrompt:@"Reauthenticating User"]; textOutput.text = @""; - [_oauthAPI authenticate]; + [_oauthAPI beginAuthentication]; } @end diff --git a/Source/Test App/OAuthClientController.m b/Source/Test App/OAuthClientController.m index 12ab3c6..11e7a30 100644 --- a/Source/Test App/OAuthClientController.m +++ b/Source/Test App/OAuthClientController.m @@ -50,7 +50,7 @@ - (IBAction)performAuthentication:(id)sender { authenticationURL:[NSURL URLWithString:[authenticationURLField stringValue]] andBaseURL:[NSURL URLWithString:[baseURLField stringValue]]]; } else { - [_oauthAPI authenticate]; + [_oauthAPI beginAuthentication]; } }