Retrieving Twitter OAuth Token using Social Framework (iOS6)
Asked Answered
W

4

23

I'm a little confused as to how I get the Twitter OAuth Token using the iOS Social Framework. Assuming I have a Facebook and Twitter account setup on iOS6, and I can get the ACAccount. When I check the ACAccountCredential for the Facebook ACAccount the OAuthToken property is set but for the Twitter ACAccount it isn't. Every other detail for the Twitter ACAccount is set just the ACAccountCredential is not.

To add to the confusion I came across an article on using Reverse Auth to get the OAuth Token (https://dev.twitter.com/docs/ios/using-reverse-auth). This article talks about calling https://api.twitter.com/oauth/request_token and passing in a dictionary of oauth_* params params e.g. consumer_key, nononce, etc. But, surely attaching my ACAccount to the SLRequest serves this purpose? In any event I get back the error "Failed to validate oauth signature and token" when I try this.

So my question is should I be seeing the Twitter OAuth Token in the ACAccountCredential, or should I be using Reverse Auth? and if so, do I need to explicit pass in the NSDictionary containing the oauth_* params or is attaching the ACAccount sufficient?

Wiese answered 14/2, 2013 at 12:22 Comment(0)
B
17

Let's answer this in a few steps, there are a few things that need addressing/clarifying.

ACAccountCredential

This object is used in co-ordination with an ACAccount object, in order for the accounts framework to be able to authenticate the user for a particular account. It is not designed to be read at will; it is only supposed to be used when you need to save an account to the accounts framework.

Documentation from Twitter states that you need to populate an ACAccountCredential if you're migrating to the accounts framework to manage your user's accounts, instead of using your own servers, or in the case of older iOS application, managing the accounts yourself locally.

Apple clearly say in their documentation that the credentials aren't able to be read after the account has been saved to the accounts framework.

For privacy reasons, this property is inaccessible after the account is saved.

As such, this is the reason why Twitter provide the ability for using reverse authentication, in case you still need the OAuth token for server side management. I don't know why you're able to get it for a Facebook account, but for Twitter you can't jump straight to a pre saved ACAccountCredential.

Using Twitter's Reverse Auth

The documentation provided by Twitter (linked in your question) makes the process fairly clear on what you need to do in order to access the OAuth access token, but I'll try to clarify a few things that may not be so clear.

There is an extra framework required, in addition to the Accounts and Twitter framework, to make this work; Social.framework. Make sure this is imported, as this will make requesting the token considerably simpler.

As for the request you need to send, Twitter is not aware of ACAccounts. Remember this reverse auth process is not specific to iOS, it can be done by any computing device with access to the web. As such, you need to send a HTTP POST request to https://api.twitter.com/oauth/request_token with the specified parameters (OAuth standard ones + x_auth_mode). A bit more clarity on the required parameters can be found here, but the link in your question will also make clear which parameters are required. You will be required to provide your own nonce, and other parameter values.

You can use the SLRequest class or AFNetworking to make your POST request to Twitter, passing in an NSDictionary for your parameter values (as seen in the code sample in Twitter's documentation for access_token).

And that's it

After answering those two points, I think it's clear that you'll need to use reverse authentication in order to access the correct OAuth token for your needs. The Twitter documentation makes it clear on what you need to do (it even provides code samples that you can use), but you do need to be aware of general OAuth request/response management in order to do so. You can't simply attach an ACAccount, you need to populate a dictionary with the required OAuth parameters, and then pass this in to your HTTP POST request to request_token. I have provided a considerable number of references for you to refer to, and I hope that'll put you on the right path.

Brieta answered 16/2, 2013 at 16:41 Comment(0)
T
7

Assuming you are going to try this on >= iOS 5.0, here is an easier way to get the access token. Irrespective of whether you are using Twitter.framework or Social.framework, the way both work is by doing the request signing for you. We use either TWRequest or SLRequest to create your request. Once we are done with this, we get the NSURLRequest object from either of these.

The trick here is to look at the headers of this NSURLRequest. As we have to specify, as per OAuth standards, a few OAuth parameters and oauth_token being one of them, it should be easy to extract it out. Below is a way to get this out.

NSURLRequest * reqTemp = /* Prepare the request using either Twitter.framework or Social.framework */;
NSDictionary * dictHeaders = [reqTemp allHTTPHeaderFields];

NSString * authString = dictHeaders[@"Authorization"];
NSArray * arrayAuth = [authString componentsSeparatedByString:@","];
NSString * accessToken;
for( NSString * val in arrayAuth ) {
    if( [val rangeOfString:@"oauth_token"].length > 0 ) {
        accessToken =
            [val stringByReplacingOccurrencesOfString:@"\""
                                           withString:@""];
        accessToken =
            [accessToken stringByReplacingOccurrencesOfString:@"oauth_token="
                                                        withString:@""];
        break;
    }
}

May be this code can be optimized more but you get the idea. The variable accessToken will have the actual access token.

Tropopause answered 6/7, 2013 at 1:2 Comment(0)
H
3

Actually if your only concern is to retrieve the OAuth token, there is a very simple way to access this using the Social Framework. Inside the documentation lies a method called:

func preparedURLRequest() -> NSURLRequest!

Return Value An OAuth-compatible NSURLRequest object that allows an app to act on behalf of the user while keeping the user’s password private. The NSURLRequest is signed as OAuth1 by default, or OAuth2 by adding the appropriate token based on the user’s account.

Discussion Use this method to modify your request before sending. By setting the account correctly, this method will automatically add any necessary tokens.

So you can just simply create a signed SLRequest like this:

let accounts = self.accountStore.accountsWithAccountType(type)
let request = SLRequest(
                forServiceType: SLServiceTypeTwitter,
                requestMethod: .GET,
                URL: NSURL(string: "https://api.twitter.com/1.1/account/verify_credentials.json"),
                parameters: ["include_entities": true])      
request.account = accounts?.first as? ACAccount

and now simply access the request.preparedURLRequest().allHTTPHeaderFields() And you'll see the oauth_token in it.

However you won't have the Secret token (because it's used to generate the oauth_signature as per twitter documentation) which makes this pretty useless for server side management.

Halcyon answered 16/9, 2014 at 0:20 Comment(0)
P
1

Check out this project https://github.com/seancook/TWReverseAuthExample. There is TWAPIManager class which does the job for you.

Policy answered 18/7, 2014 at 9:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.