Foreword
Killing a day is real, especially considering the most recent authorization of twitter compared to, for example, the same facebook.
For comparison, the algorithm for obtaining authorization:
twitter
Gets token -> I use this token, go to the login page -> We are waiting for user authorization and get a new token by callback_url -> exchange the token for the token of the secret.
facebook
We open the facebook login page with the calback_url parameter and other options -> we wait for authorization and on the callback we get the secret token that can be used.
')
Yes, I do not argue, there is an SDK from both social networks, there are built-in entries, but I needed to implement this particular authorization method. Because others are already quite beautifully implemented and there are many libraries. But what to do if the embedded records are not activated, or have been deactivated. Do not force the user to go into the settings. While he will crawl can forget about the application. Therefore, I sat down to develop a login through the web for facebook and twitter.
But I wanted to talk specifically about twitter, because, as I said above, twitter has just a huge amount of pitfalls compared to other social networks providing oAuth1 / 2
And so they drove. For development, I decided to use the STTwitter pod library because I didn’t want to shut up and write quantifiers (oh yes for oauth 1 if suddenly someone doesn't know you need to send a checksum of all the request header parameters what I personally was lazy about). It is necessary to say a surprisingly good library, but there is no documentation for it (actually, therefore, I decided to post my decision). Otherwise, everything is standard.
Step 1 together with 2
First of all, you need to get the first token, which is not at all clear why you need it. Well, okay, no arguing against the system. Everything is simple, you need to send an authorization according to the application (api keys) and checksums in a post request.
Running a little ahead: using the received token we have to make a link by which we will send the user. In order not to lose the user (not letting him go out of the layout) could be done quite simply: open a safari, then callback_url and custom url schemes for the application (for example myappscheme: // parseresult) to return to the application and partake the parameters transmitted by twitter. And here he is the first underwater stone - twitter does not allow to register custom schemes url. Because of this, return to the application under this scheme becomes impossible. How to be? I'll have to do a custom UIWebView and just had a cold delegate method of webView: shouldStartLoadWithRequest: intercept and check the download links of our UIWebView. Now it remains to make a callback to some unrealistic domain (which will not load all the same, or to change it to a real one, just in case the application has a website) of type
getmetothewounderlandandfeedmewitharainbownearpinkunicorns.comAs soon as the method sees that the web view has received a command to load this domain, we complete its work and parse the parameters for a token.
I have all the logic for referring to the STT library in separate classes, I think it will be clear that where, therefore, I’ll stress what I’m from, the more I write in sufficient detail.
By the STTwitter library, this is done simply:
Immediately lazy initialization, which I learned from a rabid old man from Senford: D (who knows he will understand). I cut out all the extra husk like checking for internal accounting in the system and so on.
A bit of controller:
- (IBAction)loinTwitterButtonClicked:(id)sender { twitter = [twitterEngine new];
Class:
-(void)sendRequestToken { [self.oauth postTokenRequest:^(NSURL *url, NSString *oauthToken) { [self.delegate openWebViewWithUrl:url];
And again the controller (here is the protocol method, and a delegate from the UIWebView that intercepts the download URLs
-(void) openWebViewWithUrl:(NSURL *)url {
Step 3
And the last campaign. To study the STT library on this topic (last step) I killed the most time, and the solution turned out to be a couple of lines. But, as I wanted, I avoided the main thing, fussing with the checksum and the connections are all in the headers. I also want to note that due to the stupidity of oAuth1 from twitter, the exchange of the token oauth_verifier is not through the header (!!!) as it was done in the previous steps, but rather the body of the POST request itself. This is where STT stuck a stick in my wheel. As it turned out, STT does not have a direct work tool through the authorization scheme I chose, namely, it does not have an oauth_verifier exchange method for an oauth_token_secret. I had to go deeper and use very deep methods of superclasses, which in fact were almost a simple system reference method. A little retreating - I know the http protocol, I can, but it was enough for me to tinker with sockets in due time so that I hated such low-level work with protocols. It is closer to me if you can say the programming of the middle levels (not UI but not direct protocols). But there was no way back, and I was already preparing to write my additional method that implements the token exchange. God, digging into someone else's code, and even writing it, is a nightmare for me, if only because it was not me who wrote it. But there was nowhere to go ... as a friend, I noticed a familiar term variable @ “oauth_verifier” and immediately began to learn the method where it was noticed. In general, why I did not guess to use the search for this key I don’t know until now. Would save a few hours.
What turned out to be: there is Twitter authorization by pin code. The scheme is similar, but it is implemented just for applications that can’t callback inside and thus get a token for exchange. In fact, the PIN in this scheme is a simplified (well, damn, remember from the site of 8 digits and enter them in the application?) Token for exchange. And since I have never studied the authorization scheme by pin (and vseravno it is documented by two paragraphs, even in the knowledge base of twitter), I did not know that they have one mechanism. Fortunately, I decided to call my method similar to
postAccessTokenRequestWithPIN: successBlock: errorBlock:
This is the very method of the library STT which, in fact, implemented what I needed. A couple of keystrokes and we get the last method of the twitterEngine class that implements the exchange of a token to a token secret and put it in a pocket for later recovery:
-(void)sendAccessToken:(NSString *)oauth_verifier { [self.oauth postAccessTokenRequestWithPIN:oauth_verifier successBlock:^(NSString *oauthToken, NSString *oauthTokenSecret, NSString *userID, NSString *screenName) { [[NSUserDefaults standardUserDefaults] setObject:oauthToken forKey:TWI_STORE_AUTH_TOKEN]; [[NSUserDefaults standardUserDefaults] setObject:oauthTokenSecret forKey:TWI_STORE_AUTH_SECRET]; [[NSUserDefaults standardUserDefaults] synchronize]; } errorBlock:^(NSError *error) {
Conclusion
Essentially everything. Further, the work lay on checking the internal recording in the phone that the STT is able to do in fact right in the implementation. If you have any thoughts on how to improve this solution, it will be interesting to listen. Especially since, by nature, as an iOS developer, I tend to abuse protocols and observings, I really like them.