Sunday 9 November 2014

ASP.NET Identity 2.0 Cookie & Token Authentication

This tutorial is centered around building an application that will support multiple platforms. The need to support a web application along with a complement of mobile apps is not uncommon. This tutorial will focus on setting up ASP.NET Identity 2.0 in a ASP.NET MVC application with WebAPI Support.

Update: If you are interested in two factor authentication then check out my new article on ASP.NET Identity 2.0 Two Factor Authentication

Use Case

The need for an authentication solution what will support both web and a native mobile application is a real need. One user store multiple authentication methods. We will need the web application to authentication using cookies and the mobile counterpart will need to use a token-based authentication.

What We Are Using?

  • Visual Studio 2013 – MVC/Individual Authentication project Template
  • ASP.NET Identity 2.0 (Pre-release)
  • ASP.NET MVC 5 & WebAPI
  • OWIN Identity Middleware

Install Prerequisites

I am using a ASP.NET MVC template with Individual Authenication found in the Visual Studio 2013 project setup. At the time this article was written, ASP.NET Identity 2.0 was still in pre-release. To demo the ASP.NET Identity 2.0 I updated my Nuget Identity packages to the pre-release versions. I have listed below the details of the packages used (some are defaults of the Visual Studio project initialization).
Id                             Version              Description/Release Notes                                                                                                                 
--                             -------              -------------------------                                                                                                                 
Antlr                          3.4.1.9004           ANother Tool for Language Recognition, is a language tool that provides a framework for constructing recognizers, interpreters, compile...
bootstrap                      3.0.0                Sleek, intuitive, and powerful front-end framework for faster and easier web development.                                                 
EntityFramework                6.1.0-beta1          Entity Framework is Microsoft's recommended data access technology for new applications.                                                  
jQuery                         1.10.2               jQuery is a new kind of JavaScript Library....                                                                                            
jQuery.Validation              1.11.1               This jQuery plugin makes simple clientside form validation trivial, while offering lots of option for customization. That makes a good ...
Microsoft.AspNet.Identity.Core 2.0.0-beta1          Core interfaces for ASP.NET Identity.                                                                                                     
Microsoft.AspNet.Identity.E... 2.0.0-beta1          ASP.NET Identity providers that use Entity Framework.                                                                                     
Microsoft.AspNet.Identity.Owin 2.0.0-beta1          Owin implementation for ASP.NET Identity.                                                                                                 
Microsoft.AspNet.Mvc           5.0.0                This package contains the runtime assemblies for ASP.NET MVC. ASP.NET MVC gives you a powerful, patterns-based way to build dynamic web...
Microsoft.AspNet.Razor         3.0.0                This package contains the runtime assemblies for ASP.NET Web Pages. ASP.NET Web Pages and the new Razor syntax provide a fast, terse, c...
Microsoft.AspNet.Web.Optimi... 1.1.1                ASP.NET Optimization introduces a way to bundle and optimize CSS and JavaScript files.                                                    
Microsoft.AspNet.WebApi        5.0.0                This package contains everything you need to host ASP.NET Web API on IIS. ASP.NET Web API is a framework that makes it easy to build HT...
Microsoft.AspNet.WebApi.Client 5.0.0                This package adds support for formatting and content negotiation to System.Net.Http. It includes support for JSON, XML, and form URL en...
Microsoft.AspNet.WebApi.Core   5.0.0                This package contains the core runtime assemblies for ASP.NET Web API. This package is used by hosts of the ASP.NET Web API runtime. To...
Microsoft.AspNet.WebApi.Web... 5.0.0                This package contains everything you need to host ASP.NET Web API on IIS. ASP.NET Web API is a framework that makes it easy to build HT...
Microsoft.AspNet.WebPages      3.0.0                This package contains core runtime assemblies shared between ASP.NET MVC and ASP.NET Web Pages.                                           
Microsoft.jQuery.Unobtrusiv... 3.0.0                jQuery plugin that unobtrusively sets up jQuery.Validation.                                                                               
Microsoft.Owin                 2.0.2                Provides a set of helper types and abstractions for simplifying the creation of OWIN components.                                          
Microsoft.Owin.Host.SystemWeb  2.0.0                OWIN server that enables OWIN-based applications to run on IIS using the ASP.NET request pipeline.                                        
Microsoft.Owin.Security        2.0.2                Common types which are shared by the various authentication middleware components.                                                        
Microsoft.Owin.Security.Coo... 2.0.2                Middleware that enables an application to use cookie based authentication, similar to ASP.NET's forms authentication.                     
Microsoft.Owin.Security.Fac... 2.0.0                Middleware that enables an application to support Facebook's OAuth 2.0 authentication workflow.                                           
Microsoft.Owin.Security.Google 2.0.0                Middleware that enables an application to support Google's OpenId authentication workflow.                                                
Microsoft.Owin.Security.Mic... 2.0.0                Middleware that enables an application to support the Microsoft Account authentication workflow.                                          
Microsoft.Owin.Security.OAuth  2.0.2                Middleware that enables an application to support any standard OAuth 2.0 authentication workflow.                                         
Microsoft.Owin.Security.Twi... 2.0.0                Middleware that enables an application to support Twitter's OAuth 2.0 authentication workflow.                                            
Microsoft.Web.Infrastructure   1.0.0.0              This package contains the Microsoft.Web.Infrastructure assembly that lets you dynamically register HTTP modules at run time.              
Modernizr                      2.6.2                Modernizr adds classes to the <html> element which allow you to target specific browser functionality in your stylesheet. You don't act...
Newtonsoft.Json                5.0.6                Json.NET is a popular high-performance JSON framework for .NET                                                                            
Owin                           1.0                  OWIN IAppBuilder startup interface                                                                                                        
Respond                        1.2.0                The goal of this script is to provide a fast and lightweight (3kb minified / 1kb gzipped) script to enable responsive web designs in br...
WebGrease                      1.5.2                Web Grease is a suite of tools for optimizing javascript, css files and images. 

Some New Patterns with ASP.NET Identity 2.0

If you are not familiar with OWIN this is a effort by Microsoft to create more modular, decoupled software with quicker release cycles. MVC 5 and ASP.NET Identity uses many different OWIN middle components. If you would like to get more information about OWN you can read more about it here.
The ASP.NET Identity includes support for creating a single instance of a the UserManager and the identity DBContext per application request. To support this pattern use the follow extension methods per the IAppBuilder object:
app.CreatePerOwinContext<AppUserIdentityDbContext>(AppUserIdentityDbContext.Create);
app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);
Here is the AppManager Class:
public class AppUserManager : UserManager<AppUserIdentity>
{
    public AppUserManager(IUserStore<AppUserIdentity> store)
        : base(store) { }

    public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
    {
        var manager = new AppUserManager(new UserStore<AppUserIdentity>(context.Get<AppUserIdentityDbContext>()));
        return manager;
    }

}
To get the AppManager object during a MVC Controller execution:
private AppUserManager _userManager;
public AppUserManager UserManager
{
    get
    {
        return _userManager ?? HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
    }
    private set
    {
        _userManager = value;
    }
} 

How to Setup ASP.NET Identity 2.0 to Support Cookie and Bearer Token Authentication

Like I mention above, there is a real world need to have an application support both web-based and native mobile applications. This requires two authentication modes: Cookie Authentication for your web-based application and the token authentication for mobile/rich client scenarios.
Since the Visual Studio 2013 project setup supports Cookie authentication out of the box. So, this article will focus primarily on how to dovetail WebAPI and Token Authentication to use the same User Store.

Setup WebAPIConfig

The first task is setting up the Startup class:
    public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }

    public void ConfigureAuth(IAppBuilder app)
    {
        app.CreatePerOwinContext<AppUserIdentityDbContext>(AppUserIdentityDbContext.Create);
        app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);

        OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
        app.UseOAuthBearerAuthentication(OAuthBearerOptions);

        //...Cookie Auth Setup here...//
    }
Here we are setup the context singleton for the DBContext and UserManager (as mention above). The important part of this snippet for authentication is initializing the bearer options object and adding the UseOAuthBearerAuthentication middle ware authentication to the pipeline. This will enable the app to use Bearer Tokens for authentication.

The next task required to support WebAPI auth is to suppress cookie authentication on API requests. This is done by added in the following code to the WebApiConfig Register method.
public static void Register(HttpConfiguration config)
{
    //...Route Registration...///

    config.SuppressDefaultHostAuthentication();
    config.Filters.Add(new HostAuthenticationFilter("Bearer"));
}
The first method tells the pipeline authentication to fall through to the request handler. The second adds an authentication handler that will validate the authentication HTTP host headers. This configuration tells the handler to look at the Authorization Header value of “Bearer abcedefghijklmnopqrstuvwxyz1234567890″ as the token. More on this later.
Do Note the two methods used are extension methods found in a OWIN package. If these methods can’t be resolved you will probably need to install the following package:
`Install-Package Microsoft.AspNet.WebApi.Owin`  

Get Your Token

The HostAuthenticationFilter will look for an authorization header for all [Authorize] annotated controllers/method. This requires an authentication process that returns a bearer token. The Microsoft.Owin.Security will come in to play here. The code below shows how to create a ticket based on the user’s claims Identity and generated a token based on the security ticket. It returns a token that will expire in 30 minutes.
public String Authenticate(string user, string password)
{

    if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(password))
        return "failed";
    var userIdentity = UserManager.FindAsync(user, password).Result;
    if (userIdentity != null)
    {
        var identity = new ClaimsIdentity(Startup.OAuthBearerOptions.AuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.Name, user));
        identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userIdentity.Id));
        AuthenticationTicket ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
        var currentUtc = new SystemClock().UtcNow;
        ticket.Properties.IssuedUtc = currentUtc;
        ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30));
        string AccessToken = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
        return AccessToken;
    }
    return "failed";
}
When successfully authenticated you will get a token like hBJi26lVQwUJF6f7roDy-oVnV_VeX20m52xL2dzF1q5IQPkt3n30610UbpFl9JV75........ Passing this in with each request’s authorization header is all that is needed to authenticate the request. Be sure to include the ‘Bearer’ designation along with the token like Bearer hBJi26lVQwUJF6f7roDy-oVnV_VeX20m52xL2dzF1q5IQPkt3n30610UbpFl9JV75.......

You will now be able execute the following method that will return the userId and User name.
[Authorize]
[HttpGet]
[ActionName("ValidateToken")]
public String ValidateToken()
{
    var user = this.User.Identity;
    if (user != null)
        return string.Format("{0} - {1}", user.GetUserId(), user.GetUserName());
    else
        return "Unable to resolve user id";

}
Feel free to download the GitHub source code (or Zip) that goes along with this article.

No comments:

Post a Comment

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...