Feb 132014
 

Introduction

In Part 1, we had a brief look at OWIN/OAuth concepts, and then prepared a clean ASP.NET web forms project for integration with NuGet packages essential to supporting a lightweight integration for OAuth handling.

In Part 2  we established the information required to authenticate users against the Live Connect OAuth provider, and also established a debugging environment; it’s time for the meat of the article.

Finally, this article will demonstrate the code necessary to handle authenticated user identities.  I must stress that this is incredibly lightweight, and hopefully it will be clear what you need to consider if taking this approach to a new or existing project.

Note: This article was originally published at Sanders Technology, check here for updates to this article and related technical articles.

The Concept Applied

Let’s quickly take a look at what you’ll be implementing from a conceptual point of view.  What you’ll be doing is effectively redirecting your users to a third party.  Once they have successfully authenticated, they’ll return to your site (or app) with some sort of token or claim (query string based).

Your site or app will then exchange this information with the third party to validate it is correct and valid.  If this is successful, the third party will share a bit of information about this user with you, which you could use to tie to a local identity if you preferred.

Here’s the concept in diagram form:

image
How the OAuth process works

Armed with this knowledge, there are a few design decisions you’ll need to make.  The most obvious one is planning how you’ll handle those redirects back to your site or application, once a user has authenticated with their OAuth provider (in this article, Microsoft Live Connect/Live Accounts).

In Part 2, I briefly discussed the importance of the Redirect Domain when configuring the Live Application.  This is, in fact, the target URL that your users will be given, once they’ve authenticated.  This can be a basic URI or a specific page.  In any case, the target has to be able to handle the authentication tokens.

Enough theory, show me some code

The code to handle authentication is ridiculously simple and lightweight.  In fact, I’ve encapsulated the logic into a single class.  In my example, I’ve hardcoded the implementation to the Microsoft provider, but I’m positive you could easily write a more generic implementation which accepts multiple OAuth providers.

This class handles the following functionality:

  • Initiate authentication (redirect to oAuth provider)
  • Handle and process authentication result (from redirect URL)
  • Save/store or cache authentication results (for subsequent requests)
  • Return basic user information (if authenticated)
  • Clear or expire authentication details

using DotNetOpenAuth.AspNet; using DotNetOpenAuth.AspNet.Clients; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace YourNamespace { public static class AuthenticationHelper { /// <summary> /// Determines if a user is presently authenticated /// </summary> /// <returns>True if authenticated, else false</returns> public static bool IsAuthenticated() { var auth = //TODO: Retrieve authentication information from temp local store or cache if (auth != null && auth.IsSuccessful) { //NOTE: Hard coded to the Microsoft provider string userName = OAuthDataProvider.Instance.GetUserNameFromOpenAuth("microsoft",

auth.ProviderUserId); //TODO: verify user id is a valid user return true; } return false; } /// <summary> /// Returns the user name for the currently authenticated user /// </summary> /// <returns></returns> public static string GetUserName() { var auth = //TODO: Retrieve authentication information from temp local store or cache if (auth != null) { return auth.UserName; } return String.Empty; } /// <summary> /// Verifies the authentication from the various OpenId and OAuth services,

///returns generic Authentication Result in res variable. /// </summary> /// <returns>Authentication information (can be null)</</returns> public static AuthenticationResult VerifyAuthentication() { var ms = new MicrosoftClient("<YOUR CLIENT ID>", "<YOUR SECRET KEY>"); var manager = new OpenAuthSecurityManager(new HttpContextWrapper(HttpContext.Current), ms, OAuthDataProvider.Instance); var result = manager.VerifyAuthentication("<YOUR REDIRECT URI>"); if (result != null) { //TODO: Save authentication information to temp local store or cache } return result; } /// <summary> /// Starts the authentication process. User will be redirected away from the current page /// </summary> public static void Authenticate() { var ms = new MicrosoftClient("<YOUR CLIENT ID>", "<YOUR SECRET KEY>"); new OpenAuthSecurityManager(new HttpContextWrapper(HttpContext.Current), ms, OAuthDataProvider.Instance)
.RequestAuthentication("<YOUR REDIRECT URI>"); } /// <summary> /// Used to “unauthenticate” an authenticated user /// </summary> public static void Unauthenticate() { //TODO: Clear authentication information from temp local store or cache } } }

Class diagram views follow:

image
Class diagram view of the Authentication Handler

There is an additional class required to make use of the OpenAuthSecurityManager class – a concrete class which implements the IOpenAuthDataProvider interface.  Luckily, you don’t have much to implement for this to work successfully:

using DotNetOpenAuth.AspNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebApplication3
{
    public class OAuthDataProvider : IOpenAuthDataProvider
    {
        public readonly static IOpenAuthDataProvider Instance = new OAuthDataProvider();

        public string GetUserNameFromOpenAuth(string openAuthProvider, string openAuthId)
        {
            return openAuthId;
        }
    }
}

As you can see, I don’t even really do anything here, I’m just returning the provider-supplied value.  You could do much more with this, including your own application-specific formatting.

image

Class view of the OAuthDataProvider class

Taking a look at the runtime process

To illustrate how this all works, I’ve updated the “clean” example solution from Part 1.  I must stress, this is a very, very simple implementation, and should in no way be used in a Production website.  It’s simply to illustrate how lightweight the implementation can be.

The sample site has a master page with a simple user control on it.  This control reflects whether a user has authenticated or not, and provides a mechanism for initializing the authentication process (in short: a “login button).

I’ll now show you what the process looks like from a series of screenshots of the working solution.  In this example, I’ve made the modifications mentioned in Part 2, as I have aliased “atempuri.org” to my localhost (for debugging purposes).

I’ve also created a Live Application at the Live Connect site. Remember – you need the Client ID and Secret ID plus have set the correct Redirect URL for this to work.

The Process

To begin, I load the default page on the site.  Notice in the top left hand corner the fairly boring “[ Authenticate ]” button.  When I click the button, it redirects me to the Live Connect page to sign in with a Microsoft (formerly Live, formerly Passport) Account.

image    image
The default page / Authenticate to Microsoft

Once I have authenticated, the Microsoft site asks me to allow my application to access basic account data.

image
The user is prompted to authorise the application

Notice here that I have not supplied an application logo – doesn’t it look ugly and unprofessional?  Once the user clicks the “Yes” button, the Microsoft site redirects the user’s browser to the URI set in the Live Application’s settings – which must match the address specified in the code in your site or application.

In this case, the user’s browser is directed to http://atempuri.org/Login (with additional data in the query string).  My login.aspx page handles the request and checks that the user is not already authenticated.

image
The Login.aspx event hander code

This page forces the “VerifyAuthentication” call, and checks again OnPreRender to see if validation worked or not.  If it is successful, the user is redirected to the default page.

Below is an example of some of the information retrieved with a successful authentication:

image
Successful authentication provides very basic information

The ProviderUserId can be used to uniquely identify the authenticated user, and also provides a “friendly name” which you can use for display purposes.

image
We’ve achieved the Zen like state of “authenticated”

The default page now displays a more friendly user experience, and provides a mechanism for “logging off”.

More on the “TODO” elements of this approach

Again, I can’t stress strongly enough that this is only a simple proof of concept.  I’ve specifically cut corners here to demonstrate how little is needed to implement OAuth support for authentication.

If you look at the sample solution, there are three values you need to supply:

public static class AuthenticationHelper
{
      private const string KEYID = "<YOUR KEY>";
      private const string SECRET = "<YOUR SECRET KEY>";
      private const string REDIRECT = "http(s)://<YOUR REDIRECT URL>";
}

At a minimum you should consider doing the following with your own website or application, up-front:

  • Determine your complete security and identity requirements
  • Decide if you want  to have user profiles “local” to your application, and whether you’ll map these identities to their Provider ID
  • Consider an approach to storing or looking up the authentication data
  • Decide how your site or application should handle:
    • Unauthenticated users
    • Authenticated users
    • The location of your “Redirect URL”
  • Decide if you want to integrate this into the ASP.NET Role Provider
  • Consider using HTTPS/SSL for some or all of your site/application

That’s just a start, this barely scratches the surface.

Summary and Download

Well, I think I’ve managed to cover off all the basics of a lightweight implementation of OAuth (OWIN) using ASP.NET.  To aid you, I’ve attached a copy of the “clean” ASP.NET web forms solution, with the authentication classes and the user control included.  I’ve personally tested the solution with real Application keys and it is working as depicted here.

It’s not a bad start if you are just looking for a very lightweight way to integrate OAuth as a mechanism for identifying users, and could obviously be extended or used to integrate into your existing authentication/authorisation mechanisms.

If you’ve had any issues or have general feedback, shoot me an email: rob.sanders@sanderstechnology.com

Sample Solution

Feb 122014
 
A lightweight implementation OWIN OAuth for ASP.NET Web Forms using Visual Studio 2013 – Part 2

Introduction Where we left off in Part 1, we’d established the prerequisites to prepare either a new or existing web forms project for the implementation of a lightweight OWIN/OAuth provider. This article, Part 2, will focus on how to prepare your development environment and also how to configure for Windows Live Account authorisation. This article [...]

Feb 062014
 
A lightweight implementation OWIN OAuth for ASP.NET Web Forms using Visual Studio 2013 – Part 1

Introduction Disclaimer: this article assumes the reader is already familiar with OWIN and OAuth standards.  It is published in three parts. Late last year I wanted to implement Open Web Interface for .Net (OWIN) OAuth  functionality for an administrative subdomain.  As it happened, I wanted to specifically integrate OWIN/OAuth authentication/authorization for an existing Dynamic Data [...]

Oct 112013
 
Entity Validation and the Entity Framework – Part 2

Introduction When we left off in Part 1, we had edited the T4 template which generates Entity Framework POCO entities and had it add appropriate attributes to assist in data validation checks. The next step is to show you how we can make use of these annotations. Note: the data access code has been updated [...]

Sep 182013
 
Flexible Data Operations with the Entity Framework V6 RC1

Introduction Recently I began writing a series of articles demonstrating how you could take a blank Database schema and bring it all together with a fully integrated object relational mapping access model (Entity Framework) and then exposing the entire object graph via WCF web services in a completely detached mode.  A brief note: Generally, it’s [...]