Skip to content

Instantly share code, notes, and snippets.

@iwasrobbed
Last active August 29, 2015 13:57
Show Gist options
  • Select an option

  • Save iwasrobbed/9559783 to your computer and use it in GitHub Desktop.

Select an option

Save iwasrobbed/9559783 to your computer and use it in GitHub Desktop.

Revisions

  1. rob phillips revised this gist Mar 15, 2014. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions TwitterReverseAuth
    Original file line number Diff line number Diff line change
    @@ -92,7 +92,8 @@ static NSString *const kEvstTwitterConsumerSecretKey = @"CONSUMER_SECRET_KEY"; /
    */
    - (void)getReverseAuthHeadersWithSuccess:(void (^)(NSString *signedReverseAuthSignature))successHandler failure:(void (^)(NSString *errorMsg))failureHandler {
    NSDictionary *parameters = @{kEvstTwitterXAuthModeKey : kEvstTwitterReverseAuthKey};
    [self.twitterClient postPath:kEvstTwitterRequestTokenPath parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
    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]);
    }
    @@ -101,9 +102,10 @@ static NSString *const kEvstTwitterConsumerSecretKey = @"CONSUMER_SECRET_KEY"; /
    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
  2. rob phillips revised this gist Mar 15, 2014. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion TwitterReverseAuth
    Original file line number Diff line number Diff line change
    @@ -3,7 +3,6 @@
    // Everest
    //
    // Created by Rob Phillips on 3/14/14.
    // Copyright (c) 2014 Everest, Inc. All rights reserved.
    //

    #import <Accounts/Accounts.h>
  3. rob phillips created this gist Mar 15, 2014.
    130 changes: 130 additions & 0 deletions TwitterReverseAuth
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,130 @@
    //
    // EvstReverseAuthExample.m
    // Everest
    //
    // Created by Rob Phillips on 3/14/14.
    // Copyright (c) 2014 Everest, Inc. All rights reserved.
    //

    #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};
    [self.twitterClient postPath:kEvstTwitterRequestTokenPath parameters:parameters 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);
    }
    }];
    }

    /*!
    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