Twitter and OAuth in desktop applications
If you’re into Twitter API programming, you probably know that the end of basic authentication is here. This post delves into the question of using the OAuth authentication mechanism in desktop applications. If you know the subject, this post will give you some practical advice for C# application development. If you don’t, it’ll act as a primer on OAuth for modern web sites.
The context: A typical application making use of Twitter or another web service almost always needs to act on behalf of a user. The need might be read-only (such as reading a user’s friends list or status history), or it might be read/write, such as with a Twitter client.
Why OAuth?
First, it is necessary to define OAuth and its place in the world as a step forward from basic authentication. When I say “basic authentication”, I mean the technology of sending the users’ credentials in an HTTP header, essentially in plain text.
This approach has three main caveats. First, intercepting the HTTP traffic allows the attacker full control of the user’s account. Second, the application needs to know and store the credentials for the user. Third, since the credentials by definition mean full control, there is no way to grant a limited permission set to an application. And a fourth minor thing, more an inconvenience, is the fact that when a user changes his password, he must change it in all the applications he is using.
The Twitter API has traditionally supported both basic and OAuth approaches, but basic authentication has now been deprecated. The preceding reasons are the main causes for this.
OAuth how?
OAuth, an open protocol designed for secure API usage, builds on a fundamentally different model. The following describes a basic exchange for OAuth-based authentication. In the exchange, three parties take a role: the user (a human being), the service (e.g. Twitter) and the consuming application (i.e. the code running on the user's behalf).
- The user indicates his/her desire to use a given service provider, like Twitter.
- The consuming application issues a request to the service, asking for an URI where to push the user for authorization.
The consuming application redirects the user to the authorization URI hosted within the service.
- The service asks the user for permission. See the image to the right for an example of Twitter’s permission grant dialog. Note that a more granular permission dialog might contain checkboxes allowing the user to control the level of access to the application.
- Once user clicks Allow, he is redirected back to the application; the URI contains a token that enables the application to authenticate.
- All further API calls will be made with said authentication tokens, establishing user identity.
Details have been skipped and some mechanics may vary between services, but that’s the rough idea.
Note that one element this Twitter example presupposes is that the consuming application must be registered in beforehand. When any API calls are made, the consuming application always identifies itself, which identification Twitter then shows in the permission dialog. This makes it much harder for malicious apps to impersonate other applications. We’ll look at this in more detail shortly.
OAuth and desktop applications
The previous example had details that clearly show it was engineered for the web. For example, note the use of the word “redirect”. Works great if you’re in a browser context – and in fact, opening the permission grant dialog isn’t really a problem in any scenario, because the browser is readily available.
However, the step 5 is more of a problem. Unless the consuming application happens to be a web site, redirecting to it isn’t really possible. Well, most consuming applications work on the web, and that’s exactly the scenario OAuth has been designed for.
Yet still, there are quite a few applications that run on the desktop without a browser GUI. For these, the “redirection” must be done manually, by transferring the token through methods such as look-and-type or copy-and-paste.
xAuth then?
xAuth is a protocol that enables browserless token exchange, essentially simplifying the process to this: The application asks for user name and password and then calls an API that turns the username/password into authentication tokens.
xAuth thus provides a compromise between the values described earlier: The consuming application will get its hands on the username/password combination, but it doesn’t have to store them. If the application is benign, it will not misuse the credentials and will discard them right after getting the tokens (and storing them instead), thus bringing all of the OAuth benefits into play for the rest of the time. Malicious applications will, of course, be able to misuse the username/password combination.
Unfortunately, xAuth isn’t widely available for Twitter yet, and needs special activation by the Twitter API team. So, in the next example, we’re going to tackle this with OAuth. And while xAuth will probably become mainstream one day, the next steps will still be a valuable learning experience – xAuth is, after all, mostly a layer upon OAuth.
Twitter, OAuth and a console application
In the next example, I’m going to build a .NET console application that supports OAuth authentication, storing the authentication tokens in a local file store and then use them to allow the user to send tweets. Actually, the syntax help for the application is pretty informative of the application’s capabilities:
Syntax: TwitterOAuthDemo <command> <arguments> Valid commands and arguments are: authenticate <accountIdentifier> tweet <accountIdentifier> <text> A typical usage sequence is to call authenticate, which opens up a browser that you can use to get the OAuth PIN, then enter the PIN into the console window. Once done, you can use the tweet command to actually send tweets. Since the OAuth access tokens are stored, you only need to call authenticate once. Note that the account identifiers are only strings used in this system. The OAuth system does not need to know the actual user account name. You can use whatever identifiers you want. The identifiers will get mapped to twitter usernames at the time of authentication. For example: TwitterOAuthDemo authenticate OurNewsInEnglish TwitterOAuthDemo tweet OurNewsInEnglish "This is a hot news headline"
Ok, let’s look at how this works.
First of all, we must register the application. You do this by going into Twitter’s application registration page and entering some basic information. Perhaps the most important choice there is to denote the application as a Desktop app, so that Twitter will know to show the PIN instead of redirecting the user to another page.
When registered, you receive a pair of tokens for your application – essentially, a user name and a password. Whenever you want to access the service, you always need to authenticate yourself (the application). These tokens must be stored inside the application.
- static TwitterClientInfo clientInfo = new TwitterClientInfo {
- ConsumerKey = "DQtmU4Gs3wiAlU3Qw…",
- ConsumerSecret = "tu6oidbDb5XK5MMqmAsMQyZdkIOX0gkW…"
- };
The created clientInfo object will then be passed on into each of the method calls made to the Twitter API. In this example, I will be using the TweetSharp library, which while having reached version 1.0, is also out of support by the original authors. However, until drastic changes occur with the Twitter API, it’ll work quite OK.
The authorization part
Like stated earlier on in the syntax help example, the application does not know the Twitter username of the account it uses. So, say the user gives a command of “TwitterOAuthDemo authenticate MyAccount”. The “MyAccount” part is just an identifier within the application, necessary mostly because typing the authentication tokens would be very cumbersome indeed. What happens next?
- // Get an unauthorized token first
- var twitter = FluentTwitter.CreateRequest(clientInfo)
- .Authentication.GetRequestToken();
- OAuthToken unauthorizedToken = twitter.Request().AsToken();
This step is required to get a token, a text string that identifies the forthcoming authentication request. Even though the result is wrapped in an OAuthToken, it’s really a pair of strings pretty much like the ConsumerKey and ConsumerSecret in the example above. Looking at the generated request in Fiddler, we see this (unnecessary pieces elided for readability):
GET http://api.twitter.com/oauth/request_token HTTP/1.1 Authorization: OAuth oauth_consumer_key="DQtmU4Gs3wiAlU3Qw...", oauth_nonce="l8hn3ftmxrnw4umd", oauth_signature="C2EHUSpCJOjtgeE5ObQybJ9Q8qg%3D"
Note that while the request does contain the consumer key, it does _not_ contain the consumer secret. Rather, the message is signed with the secret (again, skipping some less relevant details). Thus OAuth protects both the user and the application from having their identity stolen: this message could not be crafted without knowing the ConsumerSecret.
The HTTP response to this message contains a token (yet another string) and its secret. With the token received, we should get the user out to Twitter to grant us the permission. This operation is really nothing more than formatting an appropriate URI, although the TweetSharp API makes it look like a complex API call. With the URI prepared, we can redirect the user to the authorization page.
- // Now get the URI of the page we're going to redirect the user into
- string authorizationUri = FluentTwitter.CreateRequest(clientInfo).Authentication.GetAuthorizationUrl(unauthorizedToken.Token);
- System.Diagnostics.Process.Start(authorizationUri);
- Console.WriteLine("The Twitter authentication page has been opened in your default browser.");
- Console.WriteLine("Please authenticate and return with the PIN code.");
- Console.WriteLine();
- Console.Write("PIN code: ");
- string pin = Console.ReadLine().Trim();
In this example, the URI opened by the default browser was http://api.twitter.com/oauth/authorize?oauth_token=pzvqEf1HybC4z… – i.e. it contained the token returned by the previous API call to request_token. Now, the user gets to see the authorization page shown earlier in this blog post. When he clicks Allow, he gets the PIN code he then can type into to the application.
- OAuthToken accessToken =
- FluentTwitter.CreateRequest(clientInfo)
- .Authentication.GetAccessToken(unauthorizedToken.Token, pin)
- .Request().AsToken();
With the PIN, we now use the original unauthorized token and the given PIN code to verify the login. The response to this request is an authorized token – again, essentially a pair of strings. Looking at this request in Fiddler (with nonrelevant parts sliced off):
GET http://api.twitter.com/oauth/access_token HTTP/1.1 Authorization: OAuth oauth_consumer_key="DQtmU4Gs3wiAlU3Qw...", oauth_token="pzvqEf1HybC4zD7MbIqiJzuuAMnsyqmQrsb1WdzOVbE", oauth_signature="jJ%2BEYt72JT548tZsTNw725Er5Ko%3D", oauth_verifier="8771529"
For a response, we get (headers removed):
oauth_token=185590444-Z4PWQNxM4PnoWMZfAXhJMOgjA0alTy8d2s3QVJv6& oauth_token_secret=SxMO9duioXhRcpf1llXWdppEdAEIqgYfE9APrpQcjc
It is now this pair of strings we need to store for future use and pass them in each of our requests.
Next, we store them locally. There is a hand-written TokenStore class for this purpose, but its implementation is irrelevant and needs no revising here. Check out the source package if you’re interested.
Tweeting with the credentials
With the OAuth credentials stored, we can now use them to create requests. The Tweet method thus becomes extremely simple, the core being this:
- var twitter =
- FluentTwitter.CreateRequest(clientInfo)
- .AuthenticateWith(authToken.Token, authToken.Secret)
- .Statuses().Update(message);
- TwitterResult response = twitter.Request();
While the clientInfo structure contains the identity of the application, it is the AuthenticateWith call that specifies the user credentials. But again, note that the application only stores the oauth_token and oauth_token_secret – it does not store or even know the username. The account identifiers are only used as easy-to-type names for tokens inside the application – Twitter knows nothing about them.
Look at the request at the HTTP level:
POST http://api.twitter.com/1/statuses/update.json HTTP/1.1 Authorization: OAuth oauth_consumer_key="DQtmU4Gs3wiAlU3Qw...", oauth_token="185590444-Z4PWQNxM...", oauth_signature="opZPjnyd1PQg2tz%2FEd1hhPi95po%3D" status=ThisIsMyNewStatus
As you can see, the oauth_token_secret is not conveyed in the request, but again, rather used as a part in signing the message. Thus, anyone capturing this request could not use it to hijack the application’s access to the user’s account.
Where’s the source?
Here, go get it. The source compiles to a fully functional executable with two additions: First, you need to download TweetSharp and fix the references in the project, and second, you must register your application in Twitter, then fill in the OAuth consumer key and secret from the Twitter site to the initialization of the ClientInfo structure (the source has my test app’s keys removed).
Have fun!
September 2, 2010
·
Jouni Heikniemi ·
10 Comments
Tags: OAuth, Twitter · Posted in: .NET, Web
10 Responses
Jemm - September 2, 2010
Thanks for the nice post – may be useful example someday :)
yoshi - October 7, 2010
Very nice article. Concise, through, and easy to understand!
Helped me a lot. Thanks
Klamueserer - March 28, 2012
Good article!
Do I understand right, that a complete GUI-less authentication is only possible with xAuth?
best regards
Jouni Heikniemi - March 28, 2012
Klamueserer: Yes.
Klamueserer - April 2, 2012
@Jouni Heikniemi: Thanx!
Brad Berson - June 16, 2013
Hi, I found this web page about the .NET console app for tweeting via oAuth while searching for Windows command line tools to do exactly that.
It has been a while since I have played with IDEs and anything more sophisticated than VBscripts. I have been looking for a command line tweeting tool for a while, something that doesn't rely on Perl, PHP, etc. in the hopes of making it easier to use and help others use. I found one a few days ago, called TWT. And just found one more called TweetCmdr. The first one seems to have one very annoying issue when used in batch. Perhaps the second one is better. I'll be testing it tomorrow.
If TweetCmdr does not work out well, I was wondering if you had anything compiled to EXE that would be easy to set up and use?
Sincerely,
Brad Berson
Jouni Heikniemi - June 16, 2013
Brad, unfortunately I have nothing for your purpose. Although this set of sources is fairly close to what you're looking for, it will require some modification – and of course, compilation. Furthermore, I haven't tested the code recently, and Twitter may have changed something in their APIs. The concepts are certainly valid, but minor changes may have occurred. Unfortunately.
Deepak Mishra - July 11, 2013
Well written. Helped me understand OAuth.
download youtube online - July 5, 2018
I went over this web site and I believe you have a lot of fantastic
info, saved to fav (:.
https://www.start-bookmarks.win/financier-grand-marina-sai-gon-masterise-group - March 7, 2021
Various BNT examination pictures oft evoked a logical identify
former than the peerless specified in the psychometric test.
Soaked with beautiful pictures and a set of info. The invention of your site says a hatful nearly your companion.
Leave a Reply