Using Reverse Auth

Updated on Mon, 2012-11-19 18:00

While the Twitter framework for iOS provides an incredibly easy way to make authenticated calls on behalf of a user to the Twitter API, you may find the need to process a user’s Twitter data on your server. To faciliate this, Twitter provides an endpoint that allows you to obtain the user's OAuth tokens for your own application. The process is called Reverse Auth.

Before We Start

Reverse Auth is still OAuth.The reverse auth flow is not a complicated process, but it does require the ability to make a signed request. As such, you should be familiar with the request signing process before attempting to use the endpoint. No, seriously. Go read that document. We'll wait.

The Twitter framework (iOS5) or Social Framework (iOS6) is required. Before we begin, you should add the Twitter framework to your project if you have not already. And of course you should ensure that the user has an account saved on the device (otherwise, this exercise will be fruitless).

Step 1: Obtain a Special Request Token

First, you make an HTTPS request to the Twitter Request Token URL https://api.twitter.com/oauth/request_token with your application's consumer key. In addition to the conventional oauth_* signing parameters, you must also include x_auth_mode set to the value reverse_auth.

As an example, consider a request with the following values signed with the token secret ydC2yUbFaScbSlykO0PmrMjXFeLraSi3Q2HfTOlGxQM:

The tokens used here are for demonstration purposes only, and will not work for you.

  • oauth_consumer_key JP3PyvG67rXRsnayOJOcQ
  • oauth_nonce 1B7D865D-9E15-4ADD-8165-EF90D7A7D3D2
  • oauth_signature_method HMAC-SHA1
  • oauth_timestamp 1322697052
  • oauth_version 1.0
  • x_auth_mode reverse_auth

These parameters should result in a signature base string that looks like this:

  1. POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_consumer_key%3DJP3PyvG67rXRsnayOJOcQ%26oauth_nonce%3D1B7D865D-9E15-4ADD-8165-EF90D7A7D3D2%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1322697052%26oauth_version%3D1.0%26x_auth_mode%3Dreverse_auth

This call should result in a response that looks like this. Notice that this response actually looks like an OAuth header.

(line wrapping added for clarity):

  1. OAuth oauth_nonce="xq2maKtilFhVTC1MSxVC4cQIJLd53O6w97YmrdOGSk8", 
  2. oauth_signature_method="HMAC-SHA1", 
  3. oauth_timestamp="1322697052", 
  4. oauth_consumer_key="JP3PyvG67rXRsnayOJOcQ", 
  5. oauth_token="5mgkU82W0PTA0DLgSIA5vFK6c08i8dXzrbLnX06vl38", 
  6. oauth_signature="aOM%2FwW2kAowAeHBRvw7faH245p0%3D", 
  7. oauth_version="1.0"

Step 2: Obtain the Access Token

We are now going to make a request to the OAuth Access Token endpoint, https://api.twitter.com/oauth/access_token, using the TWRequest provided by the Twitter framework. If you are not familiar with TWRequest, review API requests with TWRequest.

You will need to POST to the endpoint and you must include two parameters:

  • x_reverse_auth_target Your app's consumer key (e.g. "JP3PyvG67rXRsnayOJOcQ")
  • x_reverse_auth_parameters The string value returned in Step #1

This code sample includes extraneous line breaks for readability, and uses Automatic Reference Counting (ARC).

  1. //  Assume that we stored the result of Step 1 into a var 'resultOfStep1'
  2. NSString *S = resultOfStep1;
  3. NSDictionary *step2Params = [[NSMutableDictionary alloc] init];
  4. [step2Params setValue:@"JP3PyvG67rXRsnayOJOcQ" forKey:@"x_reverse_auth_target"];
  5. [step2Params setValue:S forKey:@"x_reverse_auth_parameters"];            
  6.  
  7. NSURL *url2 = [NSURL URLWithString:@"https://api.twitter.com/oauth/access_token"];
  8. TWRequest *stepTwoRequest = 
  9. [[TWRequest alloc] initWithURL:url2 parameters:step2Params requestMethod:TWRequestMethodPOST];
  10.  
  11. //  You *MUST* keep the ACAccountStore alive for as long as you need an ACAccount instance
  12. //  See WWDC 2011 Session 124 for more info.
  13. self.accountStore = [[ACAccountStore alloc] init];
  14.  
  15. //  We only want to receive Twitter accounts
  16. ACAccountType *twitterType = 
  17. [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
  18.  
  19. //  Obtain the user's permission to access the store
  20. [self.accountStore requestAccessToAccountsWithType:twitterType 
  21. withCompletionHandler:^(BOOL granted, NSError *error) {
  22. 	if (!granted) {
  23. 		// handle this scenario gracefully
  24. 	} else {
  25. 		// obtain all the local account instances
  26. 		NSArray *accounts = 
  27. 		[self.accountStore accountsWithAccountType:twitterType];
  28.  
  29. 		// for simplicity, we will choose the first account returned - in your app,
  30. 		// you should ensure that the user chooses the correct Twitter account
  31. 		// to use with your application.  DO NOT FORGET THIS STEP.
  32. 		[stepTwoRequest setAccount:[accounts objectAtIndex:0]];
  33.  
  34. 		// execute the request
  35. 		[stepTwoRequest performRequestWithHandler:
  36. ^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
  37. 			NSString *responseStr = 
  38. 			[[NSString alloc] initWithData:responseData 
  39. encoding:NSUTF8StringEncoding];
  40.  
  41.                         // see below for an example response
  42.                         NSLog(@"The user's info for your server:\n%@", responseStr);
  43. 		}];
  44. 	} 
  45. }];

If things worked properly, you should receive a response that looks like this.

  1. oauth_token=2311112785-EXKeLV5ezo3HHIaIf1T3ffeww0mR5dfYXKZjjRy0&oauth_token_secret=KYxxxxx3U4Fxrxva3BGD92--12ehEzFwQ&user_id=38895958&screen_name=theseancook