Last active
August 29, 2015 13:57
-
-
Save iwasrobbed/9559783 to your computer and use it in GitHub Desktop.
Example of how to use AFOAuth1Client to do reverse auth of an ACAccount
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// EvstReverseAuthExample.m | |
// Everest | |
// | |
// Created by Rob Phillips on 3/14/14. | |
// | |
#import <Accounts/Accounts.h> | |
#import "EvstReverseAuthExample.h" | |
#import "AFOAuth1Client.h" | |
static NSString *const kEvstTwitterBaseURL = @"https://api.twitter.com"; | |
static NSString *const kEvstTwitterXAuthModeKey = @"x_auth_mode"; | |
static NSString *const kEvstTwitterXAuthReverseParams = @"x_reverse_auth_parameters"; | |
static NSString *const kEvstTwitterXAuthReverseTarget = @"x_reverse_auth_target"; | |
static NSString *const kEvstTwitterReverseAuthKey = @"reverse_auth"; | |
static NSString *const kEvstTwitterRequestTokenPath = @"/oauth/request_token"; | |
static NSString *const kEvstTwitterAccessTokenPath = @"/oauth/access_token"; | |
typedef void(^TwitterKeyPairHandler)(NSString *oauthToken, NSString *oauthSecret); | |
static NSString *const kEvstTwitterConsumerKey = @"CONSUMER_KEY"; // Don't share these in a public repo | |
static NSString *const kEvstTwitterConsumerSecretKey = @"CONSUMER_SECRET_KEY"; // Don't share these in a public repo | |
@interface EvstReverseAuthExample () | |
@property (nonatomic, strong) AFOAuth1Client *twitterClient; | |
@end | |
@implementation EvstReverseAuthExample | |
#pragma mark - Singleton & Class Init | |
+ (instancetype)sharedInstance { | |
static id sharedInstance = nil; | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
sharedInstance = [[self alloc] init]; | |
}); | |
return sharedInstance; | |
} | |
- (instancetype)init { | |
if (self = [super init]) { | |
// Setup the Twitter OAuth1 client | |
self.twitterClient = [[AFOAuth1Client alloc] initWithBaseURL:[NSURL URLWithString:kEvstTwitterBaseURL] | |
key:kEvstTwitterConsumerKey | |
secret:kEvstTwitterConsumerSecretKey]; | |
} | |
return self; | |
} | |
#pragma mark - Reverse Auth | |
// Note: The following was adapted from: https://github.com/seancook/TWReverseAuthExample | |
/*! | |
Performs reverse auth for the given account in order to exchange the iOS token for a verified Twitter access/secret token pair | |
\param account The @c ACAccount for which you wish to exchange tokens after being granted access by the user | |
*/ | |
- (void)performReverseAuthForAccount:(ACAccount *)account success:(TwitterKeyPairHandler)successHandler failure:(void (^)(NSString *errorMsg))failureHandler { | |
NSParameterAssert(account); | |
[self getReverseAuthHeadersWithSuccess:^(NSString *signedReverseAuthSignature) { | |
[self exchangeTokensForAccount:account signature:signedReverseAuthSignature success:^(id responseData) { | |
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; | |
NSArray *components = [responseString componentsSeparatedByString:@"&"]; | |
NSMutableDictionary *response = [[NSMutableDictionary alloc] initWithCapacity:components.count]; | |
for (NSString *keyWithValueSeparatedByEqualSign in components) { | |
NSArray *keyWithValue = [keyWithValueSeparatedByEqualSign componentsSeparatedByString:@"="]; | |
[response setValue:keyWithValue.lastObject forKeyPath:keyWithValue.firstObject]; | |
} | |
NSString *oauthToken = [response objectForKey:@"oauth_token"]; | |
NSString *oauthSecretToken = [response objectForKey:@"oauth_token_secret"]; | |
NSLog(@"Received this data: %@ and %@", oauthToken, oauthSecretToken); | |
if (successHandler) { | |
successHandler(oauthToken, oauthSecretToken); | |
} | |
} failure:^(NSString *errorMsg) { | |
if (failureHandler) { | |
failureHandler(errorMsg); | |
} | |
}]; | |
} failure:^(NSString *errorMsg) { | |
if (failureHandler) { | |
failureHandler(errorMsg); | |
} | |
}]; | |
} | |
/*! | |
Step 1: In this step, we sign and send a request to Twitter to obtain an authorization header | |
*/ | |
- (void)getReverseAuthHeadersWithSuccess:(void (^)(NSString *signedReverseAuthSignature))successHandler failure:(void (^)(NSString *errorMsg))failureHandler { | |
NSDictionary *parameters = @{kEvstTwitterXAuthModeKey : kEvstTwitterReverseAuthKey}; | |
NSURLRequest *request = [self.twitterClient requestWithMethod:@"POST" path:kEvstTwitterRequestTokenPath parameters:parameters]; | |
AFHTTPRequestOperation *operation = [self.twitterClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { | |
if (successHandler) { | |
successHandler([[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]); | |
} | |
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { | |
if ([error code] != NSURLErrorCancelled && failureHandler) { | |
failureHandler(error.localizedDescription); | |
} | |
}]; | |
[operation start]; | |
} | |
/*! | |
Step 2: In this step, we send our signed authorization header to Twitter in a request that is signed by iOS | |
\param account The @c ACAccount for which you wish to exchange tokens | |
\param signedReverseAuthSignature The authorization header returned from Step 1 | |
*/ | |
- (void)exchangeTokensForAccount:(ACAccount *)account signature:(NSString *)signedReverseAuthSignature success:(void (^)(id responseData))successHandler failure:(void (^)(NSString *errorMsg))failureHandler { | |
NSParameterAssert(account); | |
NSParameterAssert(signedReverseAuthSignature); | |
NSDictionary *parameters = @{kEvstTwitterXAuthReverseParams : signedReverseAuthSignature, | |
kEvstTwitterXAuthReverseTarget : kEvstTwitterConsumerKey}; | |
NSString *absolutePath = [NSString stringWithFormat:@"%@%@", kEvstTwitterBaseURL, kEvstTwitterAccessTokenPath]; | |
SLRequest *slRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:[NSURL URLWithString:absolutePath] parameters:parameters]; | |
slRequest.account = account; | |
[slRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) { | |
if (error && [error code] != NSURLErrorCancelled && failureHandler) { | |
failureHandler(error.localizedDescription); | |
return; | |
} | |
successHandler(responseData); | |
}]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment