Sunday, May 29, 2011

NGTweet - Part 2: Authenticate user with Twitter service using OAuth Authentication

 

Background

In the previous post I started with the process of using TweetSharp to connect to Twitter. We saw how to query the tweets from the public timeline. As a Twitter client, we would also want to fetch the tweets from the people whom we are following. Also we need the ability to tweet ourselves and send direct messages or replies to others tweets as well. For all these functionalities to work we need to login to Twitter using the username and password. In this post I’ll demonstrate how to authenticate the user with Twitter service using OAuth authentication mechanism.

Register Twitter App

If you want to access the Twitter API programmatically, you need to register your application with the Twitter. This is done at http://dev.twitter.com. Its a simple process which takes less than 5 minutes. Once you have registered the app, you get two keys which are called Consumer Key and Consumer Secret. These are encrypted values which are used to uniquely identify your application. 

Authenticate user with Twitter service

In order to authenticate a user with Twitter, using Silverlight and TweetSharp API, there are multiple options available.

  • Basic Authentication

We can use basic authentication which passes the user credentials in clear text. This is definitely not the recommended approach.

  • OAuth Authentication

The second option is to use OAuth Authentication. OAuth is an open protocol to allow secure API authorization in a simple and standard method from desktop and web applications. Since Silverlight is a desktop client we can use OAuth for our needs. You can find out more about OAuth from Wikipedia.

When you register the app, you are granted OAuth access based on the options chosen during the registration process.

  • XAuth Authentication

XAuth is another open standard for authenticating user service across web. If we are building mobile clients we can use XAuth authentication. You can find more about XAuth in this article called introducing XAuth.

XAuth is not enabled by default for the newly registered app. If you intent to authenticate users using XAuth, you need to write to Twitter explaining the reasons why you need to authenticate users using XAuth. Only upon validating the details your application will be granted privileges to use XAuth authentication mechanism.

As you would have guessed from the title of the post, I’ll demonstrate how to use OAuth authentication. I have already registered a Twitter app called NGTweet and received the Consumer Key and Consumer Secret keys.

Note : Because these are secure keys and can be used in programmatically accessing Twitter API, I’ll not be sharing them with anyone. If you intend to use the code demonstrated in this series of posts you’ll have to obtain your own keys from twitter.

Build UI to authenticate users using OAuth

The way OAuth works is like a 6 step process.

  1. Create an instance of the TweetSharp’s Twitter service using the Consumer Key and the Consume Secret keys.
  2. Get the OAuthRequestToken based on the Consumer key and secret.
  3. Get the Authorization URI using the request token. This is used to redirect the user to Twitter Sign In page. User is asked to authorize the application “NGTweet” to access to Twitter profile and related details.
  4. Once the user allows the application the access to profile a random number which is called the PIN number is generated and displayed on the screen. This number needs to be inputted into the application which requested for the access.
  5. Using the request token from the 2nd step and the PIN number, an OAuthAccessToken is generated.
  6. Finally the Twitter service is accessed with the OAuthAccessToken

As said above I have the Consumer Key and Consumer Secret with me. At start up I’ll have to ensure that the Silverlight application has the OAuthAccessToken to start interacting with the twitter API. First time when the Silverlight client starts there won’t be any token available with us. So lets start by creating the token. As we did in the previous demo, all the calls to the Twitter API which are routed through TweetSharp will have to be made through our WCF service layer.

The step of authorizing the application to access the Twitter needs to be done only once. Twitter will allow the application access to its resources on subsequent visits provided the same details are supplied in the request. For this purpose, once the user is authenticated, I’ll store the access token locally and attach it to the service request. This will fail only when the user revokes the access to the application.

So lets get started. We’ll start with the UI changes from the previous demo. We haven’t authenticated the user so far. So when the user tries to login, he’ll have to perform the above mentioned steps of entering the PIN number. Lets add a textbox where the user can add the PIN once he authorizes NGTweet to access Twitter.

        <StackPanel Name="verifierPanel">
            <TextBlock Text="Enter the PIN number " />
            <TextBox Name="txtVerifier" />
            <Button Content="Verify"
                   Click="Button_Click" />
        </StackPanel
>

This will need to be shown only if the user has not been authenticated. Once the user authenticates we’ll not go through these steps. So lets look at the mechanism of checking if the user has already granted permission for the application to access Twitter. If so we’ll store the access token for the user in the Silverlight application’s local cache. Silverlight is like a sandbox and cannot access resources on the user local file system. As a result we cannot store the access token directly.


To help the developers use local storage, Silverlight offers a facility called IsolatedStorage. You can read more about IsolatedStorage on MSDN. Its one of the simplest way of storing limited amount of user specific data. I’ll make use of this to store the users access token.



        private const string _accesstoken = "accessToken";


 


        private readonly IsolatedStorageSettings userSettings;


 



        public MainPage()


        {


            InitializeComponent();


 


            userSettings = IsolatedStorageSettings.ApplicationSettings;


 


            Loaded += MainPage_Loaded;


        }


 


 



        private void MainPage_Loaded(object sender, RoutedEventArgs e)


        {


            NGTweetAuthenticationServiceClient authenticationClient = new NGTweetAuthenticationServiceClient();


 


            if (IsValidUser())


            {


                GetTweetsForUser(authenticationClient);


            }


            else


            {


                GetRequestToken(authenticationClient);


            }


        }


In the above code snippet, we have declared a variable of type IsolatedStorage.ApplicationSetting called userSettings. In the Loaded event we check if the user is valid. If so we get the tweets for the user. Otherwise we proceed to get the request token. Lets look at the GetRequestToken first. For the purpose of handling authentication, I have added a NGTweetAuthenticationService to our previous solution. The service contract looks as follows




    [ServiceContract]


    public interface INGTweetAuthenticationService


    {


        [OperationContract]


        LoginResponse Login(LoginRequest request);


 


        [OperationContract]


        GetRequestTokenResponse GetRequestToken();


 


        [OperationContract]


        GetDataResponse GetTweets(OAuthAccessToken access);


    }



We’ll look at the detail implementation of these methods later. For the moment we are interested in the GetRequestToken method. It does not take any input but returns an GetRequestTokenResponse instance. This is inline with the Request-Response Pattern that I had mentioned in the previous example. Lets examine the structure of the response object to see what will be sent as part of the response



    [DataContract]


    public class GetRequestTokenResponse


    {


        [DataMember]


        public OAuthRequestToken RequestToken { get; set; }


 


        [DataMember]


        public Uri AuthorizationUri { get; set; }


    }


This will return us a OAuthRequestToken and the AuthorizationURI. The OAuthRequestToken is a unique token issued by Twitter to each application based on the applications Consumer Key and Consumer Secret. The AuthorizationUri is the Uri to where the user should be redirected. In our case this Uri is used to redirect the user from NGTweet application to the Twitter page which is used to authorize NGTweet to access user details.Its a kind of handshaking mechanism which uses the identity of the application (NGTweet) and that of the Twitter user to allow access to resources using the API.


Once the user is redirected to the Twitter page, he’ll need to login to Twitter and authorize the NGTweet application to access the details. If the user decides to allow access, he’ll be given a PIN which will need to be handed over to the application which requested the access (NGTweet). You’ll be greeted with a screen similar to the screenshot shown below


image


The user will be presented with the same details that you provided at the time of registering your app. You can enter the valid Twitter credentials and click on Authorize App button. The generated PIN will be displayed in the screen. This PIN will need to be passed onto NGTweet.


image


image


Click on the verify button and you’ll be able to get the OAuthAccessToken based on the RequestToken and the PIN number. So lets look at what we did after receiving the request token.



        private void GetRequestToken(NGTweetAuthenticationServiceClient authenticationClient)


        {


            authenticationClient.GetRequestTokenCompleted += authenticationClient_GetRequestTokenCompleted;


            authenticationClient.GetRequestTokenAsync();


        }


The method registers the callback delegate and calls the method GetRequestToken asynchronously.



        void authenticationClient_GetRequestTokenCompleted(object sender, GetRequestTokenCompletedEventArgs e)


        {


            GetRequestTokenResponse getRequestTokenResponse = e.Result;


 


            userSettings["requestToken"] = getRequestTokenResponse.RequestToken;


 


            string javaScript = string.Format("window.open('{0}', '_blank', '', '')", getRequestTokenResponse.AuthorizationUri);


            HtmlPage.Window.Eval(javaScript);


        }


We get the response object and pull out the RequestToken and AuthorizationUri. We store the RequestToken in the user settings for further processing. Becuase of the limitations of Silverlight we cannot directly start a new process and navigate to the Uri. In order to navigate to a different web page it needs to be user initiated by means of clicking a link or a hyperlink button. But in our case we need to programmatically redirect the user to the AuthhorizationUri. We build a JavaScript string and using the HtmlPage.Window.Eval function open a new window which takes the user to Twitter authentication page.


Now lets look at what happens when the user enters the PIN into the NGTweet application.



        private void Button_Click(object sender, RoutedEventArgs e)


        {


            NGTweetAuthenticationServiceClient authenticationClient = new NGTweetAuthenticationServiceClient();


 


            authenticationClient.LoginCompleted += authenticationClient_LoginCompleted;


 


            authenticationClient.LoginAsync(


                new LoginRequest { RequestToken = (OAuthRequestToken)userSettings["requestToken"], Pin = txtVerifier.Text });


        }


 


        void authenticationClient_LoginCompleted(object sender, LoginCompletedEventArgs e)


        {


            LoginResponse loginResponse = e.Result;


 


            userSettings[_accesstoken] = loginResponse.OAuthAccessToken;


        }


We use the PIN entered by the user and using the RequestToken for the NGTweet application make a request to the authentication service’s Login method. Once again this is done asynchronously. And in the callback we retrieve the OAuthAccessToken returned by the service cache it in the user settings. We can close the application now and restart it. We’ll not be asked to enter PIN anymore. We’ll be straight away presented with the tweets from our account as shown below.


image


With almost all things done on the client side, lets look at the service implementation.


 


NGTweet Authentication Service


 



public class NGTweetAuthenticationService : INGTweetAuthenticationService


    {


        private readonly TwitterService _service;


 


        public NGTweetAuthenticationService()


        {


            _service = _service = new TwitterService("YourAppConsumerKeyHere", "YourAppConsumeSecretHere");


        }


 


        public LoginResponse Login(LoginRequest request)


        {


            OAuthAccessToken access = _service.GetAccessToken(request.RequestToken, request.Pin);


 


            _service.AuthenticateWith(access.Token, access.TokenSecret);


 


            return new LoginResponse { OAuthAccessToken = access };


        }


 


        public GetDataResponse GetTweets(OAuthAccessToken access)


        {


            _service.AuthenticateWith(access.Token, access.TokenSecret);


 


            IEnumerable<TwitterStatus> mentions = _service.ListTweetsOnHomeTimeline();


 


            TweeterStatusAdapter adapter = new TweeterStatusAdapter();


 


            return new GetDataResponse { TweeterStatuses = adapter.Convert(mentions) };


        }


 


        public GetRequestTokenResponse GetRequestToken()


        {


            OAuthRequestToken requestToken = _service.GetRequestToken();


 


            Uri uri = _service.GetAuthorizationUri(requestToken);


 


            return new GetRequestTokenResponse { RequestToken = requestToken, AuthorizationUri = uri };


        }


    }


This is a very simple implementation which does the job of transforming the objects between the TweetSharp API and our domain model. Only thing to note there is I haven’t put the actual keys for the consumer key and consumer secret while creating the service.



            _service = _service = new TwitterService("YourAppConsumerKeyHere", "YourAppConsumeSecretHere");


If you want to make use of this code, ensure that you replace these with the appropriate values.


Conclusion















In this post I demonstrated how to use the OAuth authentication mechanism to authorise NGTweet application to get access to Twitter API. The process seems bit tedious. But its inline with the OAuth standards. I built upon the previous demo to integrate authentication into the NGTweet application. In the future posts I’ll demonstrate other features like sending a tweet, retweet someone else’s tweet, set a tweet as favourite tweet, send direct message to users etc which are basic features for any Twitter client application.


As always I have uploaded the complete working solution to dropbox. I have removed the unnecessary files from the TweetSharp dependencies folder to reduce the size of the zip file. If you use NuGet package manager to add TweetSharp reference you’ll find lot more files in your packages folder.


Until next time Happy Programming Smile

2 comments:

  1. Anonymous1:15 PM

    This piece of writing is really a nice one it assists new web people, who are wishing for blogging.



    Here is my blog; Portable Executable

    ReplyDelete
  2. In 2015, Twitter API changes. Alternatives?

    ReplyDelete

Submit Apache Spark job from Command Line to HDInsight cluster

Background This is the 3rd part of the Step by Step guide to run Apache Spark on HDInsight cluster. The first part was about provisioning t...