Skip to content

Commit

Permalink
Merge pull request #59 from tumblr/dont-sign-xauth-with-token-or-secret
Browse files Browse the repository at this point in the history
Dont sign xAuth request with (potentially invalid) token or token secret
  • Loading branch information
irace committed Apr 10, 2014
2 parents e69d3a6 + bc677e9 commit 0984672
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>tumblr_auth_example</string>
<string>tumblrauthexample</string>
</array>
</dict>
</array>
Expand Down
2 changes: 1 addition & 1 deletion TMTumblrSDK.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TMTumblrSDK'
s.version = '1.0.6'
s.version = '1.0.7'
s.summary = 'An unopinionated and flexible library for easily integrating Tumblr data into your iOS or OS X application.'
s.author = { 'Bryan Irace' => 'bryan@tumblr.com' }
s.homepage = 'http://tumblr.github.com/TMTumblrSDK'
Expand Down
2 changes: 1 addition & 1 deletion TMTumblrSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@
DSTROOT = /tmp/TumblrSDK.dst;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "TMTumblrSDK/TMTumblrSDK-Prefix.pch";
ONLY_ACTIVE_ARCH = NO;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = (
"-ObjC",
"${inherited}",
Expand Down
95 changes: 54 additions & 41 deletions TMTumblrSDK/Authentication/TMTumblrAuthenticator.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@

@interface TMTumblrAuthenticator()

@property (nonatomic, copy) TMAuthenticationCallback authCallback;
@property (nonatomic, copy) NSString *OAuthToken;
@property (nonatomic, copy) NSString *OAuthTokenSecret;
@property (nonatomic, copy) TMAuthenticationCallback threeLeggedOAuthCallback;
@property (nonatomic, copy) NSString *threeLeggedOAuthTokenSecret;

NSMutableURLRequest *mutableRequestWithURLString(NSString *URLString);

NSError *errorWithStatusCode(int statusCode);
NSError *errorWithStatusCode(NSInteger statusCode);

NSDictionary *formEncodedDataToDictionary(NSData *data);

Expand All @@ -44,29 +43,31 @@ + (id)sharedInstance {

- (void)authenticate:(NSString *)URLScheme callback:(TMAuthenticationCallback)callback {
// Clear token secret in case authentication was previously started but not finished
self.OAuthTokenSecret = nil;
self.threeLeggedOAuthTokenSecret = nil;

NSString *tokenRequestURLString = [NSString stringWithFormat:@"http://www.tumblr.com/oauth/request_token?oauth_callback=%@",
TMURLEncode([NSString stringWithFormat:@"%@://tumblr-authorize", URLScheme])];

NSMutableURLRequest *request = mutableRequestWithURLString(tokenRequestURLString);
[self signRequest:request withParameters:nil];
[[self class] signRequest:request withParameters:nil consumerKey:self.OAuthConsumerKey
consumerSecret:self.OAuthConsumerSecret token:nil tokenSecret:nil];

NSURLConnectionCompletionHandler handler = ^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
if (callback)
if (callback) {
callback(nil, nil, error);
}

return;
}

int statusCode = ((NSHTTPURLResponse *)response).statusCode;
NSInteger statusCode = ((NSHTTPURLResponse *)response).statusCode;

if (statusCode == 200) {
self.authCallback = callback;
self.threeLeggedOAuthCallback = callback;

NSDictionary *responseParameters = formEncodedDataToDictionary(data);
self.OAuthTokenSecret = responseParameters[@"oauth_token_secret"];
self.threeLeggedOAuthTokenSecret = responseParameters[@"oauth_token_secret"];

NSURL *authURL = [NSURL URLWithString:
[NSString stringWithFormat:@"https://www.tumblr.com/oauth/authorize?oauth_token=%@",
Expand All @@ -79,60 +80,64 @@ - (void)authenticate:(NSString *)URLScheme callback:(TMAuthenticationCallback)ca
#endif

} else {
if (callback)
if (callback) {
callback(nil, nil, errorWithStatusCode(statusCode));
}
}
};

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:handler];
}

- (BOOL)handleOpenURL:(NSURL *)url {
if (![url.host isEqualToString:@"tumblr-authorize"])
if (![url.host isEqualToString:@"tumblr-authorize"]) {
return NO;
}

void(^clearState)() = ^ {
self.OAuthToken = nil;
self.OAuthTokenSecret = nil;
self.authCallback = nil;
self.threeLeggedOAuthTokenSecret = nil;
self.threeLeggedOAuthCallback = nil;
};

NSDictionary *URLParameters = TMQueryStringToDictionary(url.query);

if ([[URLParameters allKeys] count] == 0) {
if (self.authCallback)
self.authCallback(nil, nil, [NSError errorWithDomain:@"Permission denied by user" code:0 userInfo:nil]);
if (self.threeLeggedOAuthCallback) {
self.threeLeggedOAuthCallback(nil, nil, [NSError errorWithDomain:@"Permission denied by user" code:0 userInfo:nil]);
}

clearState();

return NO;
}

self.OAuthToken = URLParameters[@"oauth_token"];
NSString *OAuthToken = URLParameters[@"oauth_token"];

NSDictionary *requestParameters = @{ @"oauth_verifier" : URLParameters[@"oauth_verifier"] };

NSMutableURLRequest *request = mutableRequestWithURLString(@"https://www.tumblr.com/oauth/access_token");
request.HTTPMethod = @"POST";
request.HTTPBody = [TMDictionaryToQueryString(requestParameters) dataUsingEncoding:NSUTF8StringEncoding];
[self signRequest:request withParameters:requestParameters];

[[self class] signRequest:request withParameters:requestParameters consumerKey:self.OAuthConsumerKey
consumerSecret:self.OAuthConsumerSecret token:OAuthToken tokenSecret:self.threeLeggedOAuthTokenSecret];

NSURLConnectionCompletionHandler handler = ^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
if (self.authCallback)
self.authCallback(nil, nil, error);

if (self.threeLeggedOAuthCallback) {
self.threeLeggedOAuthCallback(nil, nil, error);
}
} else {
int statusCode = ((NSHTTPURLResponse *)response).statusCode;
NSInteger statusCode = ((NSHTTPURLResponse *)response).statusCode;

if (self.authCallback) {
if (self.threeLeggedOAuthCallback) {
if (statusCode == 200) {
NSDictionary *responseParameters = formEncodedDataToDictionary(data);

self.authCallback(responseParameters[@"oauth_token"], responseParameters[@"oauth_token_secret"], nil);
self.threeLeggedOAuthCallback(responseParameters[@"oauth_token"], responseParameters[@"oauth_token_secret"], nil);

} else {
self.authCallback(nil, nil, errorWithStatusCode(statusCode));
self.threeLeggedOAuthCallback(nil, nil, errorWithStatusCode(statusCode));
}
}
}
Expand All @@ -156,29 +161,32 @@ - (void)xAuth:(NSString *)emailAddress password:(NSString *)password callback:(T
NSMutableURLRequest *request = mutableRequestWithURLString(@"https://www.tumblr.com/oauth/access_token");
request.HTTPMethod = @"POST";
request.HTTPBody = [TMDictionaryToQueryString(requestParameters) dataUsingEncoding:NSUTF8StringEncoding];
[self signRequest:request withParameters:requestParameters];

[[self class] signRequest:request withParameters:requestParameters consumerKey:self.OAuthConsumerKey
consumerSecret:self.OAuthConsumerSecret token:nil tokenSecret:nil];

NSURLConnectionCompletionHandler handler = ^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
if (callback)
if (callback) {
callback(nil, nil, error);
}

return;
}

int statusCode = ((NSHTTPURLResponse *)response).statusCode;
NSInteger statusCode = ((NSHTTPURLResponse *)response).statusCode;

if (statusCode == 200) {
NSDictionary *responseParameters = formEncodedDataToDictionary(data);
self.OAuthToken = responseParameters[@"oauth_token"];
self.OAuthTokenSecret = responseParameters[@"oauth_token_secret"];

if (callback)
callback(self.OAuthToken, self.OAuthTokenSecret, nil);

if (callback) {
callback(responseParameters[@"oauth_token"], responseParameters[@"oauth_token_secret"], nil);
}

} else {
if (callback)
if (callback) {
callback(nil, nil, errorWithStatusCode(statusCode));
}
}
};

Expand All @@ -190,24 +198,29 @@ - (void)xAuth:(NSString *)emailAddress password:(NSString *)password callback:(T

#pragma mark - Helpers

- (void)signRequest:(NSMutableURLRequest *)request withParameters:(NSDictionary *)parameters {
+ (void)signRequest:(NSMutableURLRequest *)request
withParameters:(NSDictionary *)parameters
consumerKey:(NSString *)consumerKey
consumerSecret:(NSString *)consumerSecret
token:(NSString *)OAuthToken
tokenSecret:(NSString *)OAuthTokenSecret {
[request setValue:@"TMTumblrSDK" forHTTPHeaderField:@"User-Agent"];

[request setValue:[TMOAuth headerForURL:request.URL
method:request.HTTPMethod
postParameters:parameters
nonce:[[NSProcessInfo processInfo] globallyUniqueString]
consumerKey:self.OAuthConsumerKey
consumerSecret:self.OAuthConsumerSecret
token:self.OAuthToken
tokenSecret:self.OAuthTokenSecret] forHTTPHeaderField:@"Authorization"];
consumerKey:consumerKey
consumerSecret:consumerSecret
token:OAuthToken
tokenSecret:OAuthTokenSecret] forHTTPHeaderField:@"Authorization"];
}

NSMutableURLRequest *mutableRequestWithURLString(NSString *URLString) {
return [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLString]];
}

NSError *errorWithStatusCode(int statusCode) {
NSError *errorWithStatusCode(NSInteger statusCode) {
return [NSError errorWithDomain:@"Authentication request failed" code:statusCode userInfo:nil];
}

Expand Down

0 comments on commit 0984672

Please sign in to comment.