If you’re developing an application that needs to use Twitter, you’ll most likely have to authenticate in order to post tweets. If you’re using C#, you can use TweetSharp. However, I found it doesn’t really work for Windows Phone, in particular because the GetRequestToken method is missing. This is not to say the work Daniel Crenna is bad, far from it. But for a Windows Phone app I’m developing I needed to authenticate with Twitter. And finally, TweetSharp is no longer actively maintained.Luckily, Daniel also wrote a great library called Hammock which helps you call REST services. Incidentally, Hammock is used by TweetSharp. So this is how you authenticate a WP7 app with Twitter using OAuth.First, get a Twitter account and register a new application at http://dev.twitter.com. Make sure you set your Access Level to ‘Read and Write’ (under settings). ‘Sign in with Twitter’ can be left unchecked. Finally, you have to enter a callback URL. This is the URL Twitter will refer you to when you have succesfully authenticated. Of course, we don’t have a URL, as we are building a Windows Phone app. But that doesn’t matter. We will check when our phone browser is returning to this URL and than get the necessary parameters. After that, we will close the browser, and the user will never see this callback URL. I went with http://www.google.be.Then, this is the code to go to Twitter:
private void GetTwitterToken() { var credentials = new OAuthCredentials { Type = OAuthType.RequestToken, SignatureMethod = OAuthSignatureMethod.HmacSha1, ParameterHandling = OAuthParameterHandling.HttpAuthorizationHeader, ConsumerKey = "your consumer key", ConsumerSecret = "you consumer secret, Version = "1.0a", CallbackUrl = "http://www.google.be" }; var client = new RestClient { Authority = "https://api.twitter.com/oauth, Credentials = credentials, HasElevatedPermissions = true }; var request = new RestRequest { Path = "/request_token" }; client.BeginRequest(request, TwitterRequestTokenCompleted); }
What we do is create credentials with the necessary values. Next, create a RestClient and pass it the credentials. Finally, create a request, pointing to “/request_token” and begin the request.Make sure you don’t make the mistake I made and push your consumer secret to a public repository! If you do, you’ll have to remove the application from your Twitter applications and create it again. This will give you new keys. After that, I created a partial class, split up across two files, containing all my Twitter info (so I could call TwitterSettings.ConsumerSecret). One file I set my Git repository to ignore, the other I pushed to the public repository.Our next step is to handle the result of our REST request. This should give you your Token and Token Secret. In short: your consumer keys identify your application to users, the tokens identify a user using your app to Twitter. It means that Twitter can be sure that the user agreed to your app using their Twitter account.
private void TwitterRequestTokenCompleted(RestRequest request, RestResponse response, object userstate) { _oAuthToken = GetQueryParameter(response.Content, "oauth_token"); _oAuthTokenSecret = GetQueryParameter(response.Content, "oauth_token_secret"); var authorizeUrl = "https://api.twitter.com/oauth/authorize?oauth_token=" + _oAuthToken; if (string.IsNullOrEmpty(_oAuthToken) || string.IsNullOrEmpty(_oAuthTokenSecret)) { Dispatcher.BeginInvoke(() => MessageBox.Show("error calling twitter")); return; } Dispatcher.BeginInvoke(() => TwitterBrowser.Navigate(new Uri(authorizeUrl))); } private static string GetQueryParameter(string input, string parameterName) { foreach (string item in input.Split('&')) { var parts = item.Split('='); if (parts[0] == parameterName) { return parts[1]; } } return String.Empty; }
With the tokens, we navigate to the authorize url. Even though we have tokens, the user hasn’t actually agreed with us using their Twitter account yet. When they do, we’ll have to save these tokens. Next time we connect to Twitter, we’ll send the tokens along and Twitter will know what application and what user it is.The authorize url is the page where the user logs in to Twitter and grants your application access. When that’s done, Twitter will send the user back to the callback url we specified (http://www.google.be in my case). This is where we need to handle the Navigating event of the WebBrowser control we added to our Windows Phone app.
private void OnTwitterBrowserNavigating(object sender, NavigatingEventArgs e) { // I put code here to show a ProgressBar with Indetermintate = true, //but that's not really important for this post. if (!e.Uri.AbsoluteUri.Contains("http://www.google.be")) return; e.Cancel = true; var arguments = e.Uri.AbsoluteUri.Split('?'); if (arguments.Length < 1) return; GetAccessToken(arguments[1]); }
So, if it’s our callback uri, we take the query string and pass it to our GetAccessToken method:
private void GetAccessToken(string uri) { var requestToken = GetQueryParameter(uri, "oauth_token"); if (requestToken != _oAuthToken) { MessageBox.Show("Twitter auth tokens don't match"); } var requestVerifier = GetQueryParameter(uri, "oauth_verifier"); var credentials = new OAuthCredentials { Type = OAuthType.AccessToken, SignatureMethod = OAuthSignatureMethod.HmacSha1, ParameterHandling = OAuthParameterHandling.HttpAuthorizationHeader, ConsumerKey = "ConsumerKey", ConsumerSecret = "ConsumerKeySecret", Token = _oAuthToken, TokenSecret = _oAuthTokenSecret, Verifier = requestVerifier }; var client = new RestClient { Authority = "https://api.twitter.com/oauth", Credentials = credentials, HasElevatedPermissions = true }; var request = new RestRequest { Path = TwitterSettings.AccessTokenPath }; client.BeginRequest(request, RequestAccessTokenCompleted); }
What we do here is get the oauth_verifier parameter from the query string and make a new REST request. This gives us two new tokens, which we need to store. In future calls to Twitter, we’ll use these tokens so Twitter knows which app and which user is calling.
private void RequestAccessTokenCompleted(RestRequest request, RestResponse response, object userstate) { var twitterUser = new TwitterUser { AccessToken = GetQueryParameter(response.Content, "oauth_token"), AccessTokenSecret = GetQueryParameter(response.Content, "oauth_token_secret"), UserId = GetQueryParameter(response.Content, "user_id"), ScreenName = GetQueryParameter(response.Content, "screen_name") }; if (String.IsNullOrEmpty(twitterUser.AccessToken) || String.IsNullOrEmpty(twitterUser.AccessTokenSecret)) { Dispatcher.BeginInvoke(() => MessageBox.Show(response.Content)); return; } var command = new SaveTwitterUserCommand(); command.Execute(twitterUser); Dispatcher.BeginInvoke(() => { if (NavigationService.CanGoBack) { NavigationService.GoBack(); } else { NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative)); } }); }
What you do in this last step is up to you. I put the necessary data in a new object (TwitterUser), save it to the application’s isolated storage and then go back to the previous page. You can see my final code on GitHub.In my next post, I’ll show you how to post to Twitter with a photo.