This project has moved. For the latest updates, please go here.

Implementing OAuth for WebForms Applications

Web authorization includes the entire OAuth authorization flow. This page will explain how you can implement OAuth in ASP.NET Web Forms (WebForms) using LINQ to Twitter's WebAuthorizer. Before jumping into code, you'll see a high-level view of how the whole process works.
High-Level Description of Web Authorization
You'll see the details of how Web authorization is implemented with LINQ to Twitter soon, but it might be useful to review how the whole process works. It might help you know where you're at in the process when looking at later details. Here's what happens during Web authorization.

1. Some action in your code (login or a specific need to use a Twitter feature that requires authorization) initiates the authorization process.

2. Your code tells LINQ to Twitter to begin the authorization process.

3. LINQ to Twitter redirects the user to the Twitter authorization page.

4. The user authorizes your application.

5. Twitter redirects to a callback page in your application.

6. Your code tells LINQ to Twitter to complete the authorization process.

7. When authorization is complete, OAuth and Access tokens are available for you to store for this user.

Of all the previous steps, #1 and #7 are less defined. That's because those are the points that depend on how you design your application. After authorization, LINQ to Twitter can be used for any supported queries or commands.

Now that you have an idea of how the process works, let's look at an example of how you can code this with LINQ to Twitter.
Implementing Web Authorization
To get started, you'll need to instantiate an AspNetAuthorizer. This authorizer helps manage the OAuth workflow with Twitter. Here's an example:

    public partial class OAuth : System.Web.UI.Page
    {
        AspNetAuthorizer auth;

        protected async void Page_Load(object sender, EventArgs e)
        {
            auth = new AspNetAuthorizer
            {
                CredentialStore = new SessionStateCredentialStore
                {
                    ConsumerKey = ConfigurationManager.AppSettings["consumerKey"],
                    ConsumerSecret = ConfigurationManager.AppSettings["consumerSecret"]
                },
                GoToTwitterAuthorization = 
                    twitterUrl => Response.Redirect(twitterUrl, false)
            };
GoToTwitterAuthorization is an Action<string>, and the example assigns a lambda that specifies how to send the user to the Twitter authorization page. The twitterUrl parameter is the HTTP address of the Twitter authorization page. Calling Response.Redirect causes the browser to send the user to Twitter's authorization page, so the user can authorize your application. LINQ to Twitter will execute the lambda assigned to GoToTwitterAuthorization during the authorization process.

Everything you've seen is happening in the Page_Load event. You'll see more activity in Page_Load, but let's take a temporary diversion. First, look at what has happened so far: Both credentials and the AspNetAuthorizer have been set up. Looking at the big picture, the next thing that should occur is to start the authorization process, as shown in the following example:

        protected async void AuthorizeButton_Click(object sender, EventArgs e)
        {
            await auth.BeginAuthorizeAsync(Request.Url);
        }
The code above is an event handler for a button click. The code starts the authorization process by calling BeginAuthorizeAsync on the AspNetAuthorizer instance shown in the previous example. Additionally, you must pass the address of a callback page. This callback page is where Twitter redirects the user's browser after the user authorizes your application. This example uses the current page, which is Request.Url.

Now, the OAuth process has been initiated, LINQ to Twitter redirects the user to the Twitter authorization page (via GoToTwitterAuthorization on the AspNetAuthorizer instance), and Twitter redirects the user back to the callback URL. As you just saw, the callback URL is the current page. This brings us back to the Page_Load event handler, which always executes and instantiates the AspNetAuthorizer for the rest of the page, as you've already seen. Still in Page_Load and after the AspNetAuthorizer instantiation, you must complete the authorization process, like this:

            if (!Page.IsPostBack && Request.QueryString["oauth_token"] != null)
            {
                await auth.CompleteAuthorizeAsync(Request.Url);

                // This is how you access credentials after authorization.
                // The oauthToken and oauthTokenSecret do not expire.
                // You can use the userID to associate the credentials with the user.
                // You can save credentials any way you want - database, isolated 
                //   storage, etc. - it's up to you.
                // You can retrieve and load all 4 credentials on subsequent queries 
                //   to avoid the need to re-authorize.
                // When you've loaded all 4 credentials, LINQ to Twitter will let you 
                //   make queries without re-authorizing.
                //
                //var credentials = auth.CredentialStore;
                //string oauthToken = credentials.OAuthToken;
                //string oauthTokenSecret = credentials.OAuthTokenSecret;
                //string screenName = credentials.ScreenName;
                //ulong userID = credentials.UserID;
                //

                Response.Redirect("~/Default.aspx", false);
            }
To finish the OAuth process, call CompleteAuthorizeAsync on the AspNetAuthorizer instance, as shown above. After CompleteAuthorizeAsync returns, you can read OAuthToken and AccessToken and store them in the database for this user. On subsequent LINQ to Twitter queries on behalf of this same user, you can retrieve the OAuthToken and AccessToken from your database and populate CredentialStore with all four tokens. By loading all four tokens, LINQ to Twitter will not redirect the user for authorization and you can simply perform queries on behalf of that user.

This example takes a design that runs the OAuth logic on a separate page, OAuth.aspx. Notice that this example performs a re-direct to another page after CompleteAuthorizeAsync.

To perform queries, you need to instantiate a TwitterContext with the WebAuthorizer that has all four credential tokens. After redirection to another page, you can use LINQ to Twitter, like this:

        protected async void RefreshButton_Click(object sender, EventArgs e)
        {
            var auth = new AspNetAuthorizer
            {
                CredentialStore = new SessionStateCredentialStore(),
                GoToTwitterAuthorization = twitterUrl => { }
            };

            var ctx = new TwitterContext(auth);

            var tweets =
                await
                (from tweet in ctx.Status
                 where tweet.Type == StatusType.Home
                 select tweet)
                .ToListAsync();

            TwitterListView.DataSource = tweets;
            TwitterListView.DataBind();
        }
This example is a button click handler. Notice that it instantiates a new AspNetAuthorizer. The code assigns a new SessionStateCredentialStore to the CredentialStore property. Since the OAuth process has ran and the AspNetAuthorizer stored credentials in Session state, the SessionStateCredentialStore will pick up those values automatically. Since all 4 credentials are available, GoToTwitterAuthorization won't execute, and doesn't need an implementation. You can then pass the authorizer to a new instance of TwitterContext and use LINQ to Twitter as you need.
Summary
The high-level view explained how the Web authorization process works. The next section on implementation showed one way to write code for Web authorization. The AspNetAuthorizer was instantiated with CredentialStore and GoToTwitterAuthorization. In particular, remember the extensibility points with ICredentialStore and GoToTwitterAuthorization so you can customize Web authorization for your particular application. Also, pay attention to how the BeginAuthorizeAsync and CompleteAuthorizeAsync occur in different places because of browser redirection in combination with the ASP.NET page lifecycle.

Last edited Nov 29, 2013 at 5:21 AM by JoeMayo, version 5