DNVM, DNX, and DNU - Understanding the ASP.NET 5 Runtime Options

Posted on May 17 2015 08:13 PM by jatten in ASP.Net, ASP.NET MVC, C#, CodeProject   ||   Comments (6)

give-my-regards-to-mr-escher-240ASP.NET 5 introduces a new runtime model for the .NET framework which allows us to employ a "pay-as-you-go" approach, building composable applications using only those framework components our application needs, without relying upon a central, monolithic library repository present on the host machine.

This new model also provides us with command line tools for managing our .NET version selection, library packages, and execution environment outside of Visual Studio. It is now possible to develop cross-platform ASP.NET applications using a text editor and command line (either CMD or Powershell on Windows) without ever opening Visual Studio.

Image by César Astudillo  |  Some Rights Reserved

Understanding the relationship between the .NET Version Manager (DNVM), the .NET Execution Environment (DNX) and .NET Development Utilities (DNU) is fundamental to developing with ASP.NET 5. In this post we will look at installing and using DNVM, DNX, and DNU on to work with ASP.NET from the command line.

DNVM - The .NET Version Manager

DNVM is a version manager tool for the command line. As its name implies, DNVM provides the functionality needed to configure your .NET runtime. We can use DNVM to specify which version of the .NET Execution Environment to use at the process, user, or machine level.

DNX - The .NET Execution Environment

What is this DNX, anyway? From the ASP.NET Documentation site:

The .NET Execution Environment (DNX) is a software development kit (SDK) and runtime environment that has everything you need to build and run .NET applications for Windows, Mac and Linux. It provides a host process, CLR hosting logic and managed entry point discovery. DNX was built for running cross-platform ASP.NET Web applications, but it can run other types of .NET applications, too, such as cross-platform console apps.

Broadly speaking, different DNX runtime versions are available which reflect which .NET framework version you want to use in your application. At a basic level, there are different versions for:

  • .NET Framework - The familiar .NET framework we all know and love.
  • .NET Core - A subset of the .NET Framework which includes a modular runtime and library implementation and is managed via Nuget. .NET Core is cross-platform, open source, and includes the Core libraries in CoreFX, and a Core runtime in CoreCLR.
  • Mono - Using Mono, we can create ASP.NET application which compile and run on OSX and Linux machines.

We can use the .NET Version Manager to select which DNX version we want to use with our application.

DNU - .NET Development Utilities

DNU is a command-line tool which provides a variety of utility functions to assist with development in ASP.NET. Most commonly, we will use DNU to install and manage library packages in our application, and/or to package and publish our own application.

DNU uses Nuget behind the scenes for package management and deployment.

Getting Started - Installing DNVM

If you have installed Visual Studio 2015 (currently available as a Release Candidate HERE), you already have the .NET Version Manager installed.

UPDATE: According to the ASP.NET team  (thanks Glenn!) DNX/DNVM isn't actually installed until you run File -> New after VS 2015 is installed, so if you have VS 2015 installed but have not cracked open a new file yet, you won't have it on your machine yet.

If you want to upgrade to the most recent version of DNVM, or if you want to work with ASP.NET, but don't want to install Visual Studio, you can download the DNVM script as follows from either the Windows Command prompt (CMD) or using Powershell:

Install or Upgrade DNVM Using CMD:
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "&{$Branch='dev';iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.ps1'))}"

 

Install or Upgrade DNVM Using Powershell:
&{$Branch='dev';iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.ps1'))}

 

Once we have DNVM on our machine, we should be able to fire up the Windows command prompt, and get started.

At the command line (or Powershell prompt) run the following to see that DNVM is, in fact, installed on your machine:

Run DNVM without Arguments:
> dnvm

 

If all has gone well to this point, you should see the following (we're going to stick with CMD for this post, to keep things simple):

Console Output from Running DNVM without Arguments:

run-dnvm-no-args

Now that we have DNVM installed and running, let's see which DNX versions we have available, and how to install DNX versions if we need.

Working with DNVM - List the Available .NET Runtimes

To examine the runtime options available to us, we can run the following command from the Console:

List Available DNX Runtimes Using DNVM List:
> dnvm list

 

I had previously installed Visual Studio 2015 on my machine, which also installed a few DNX versions, so when I runt he above I see the following output:

Console Output from DNVM List:

run-dnvm-list

Because I had installed Visual Studio 2015 already, there are DNX versions available for .NET Framework (the beta4 clr in the image above) and also .NET Core (the coreclr above) for both 32 and 64 bit architectures.

If you have NOT installed Visual Studio 2015, your list is very likely empty. Installing DNVM does not, in and of itself, install any DNX versions on your machine. No worries, we'll take care of that next.

Working with DNVM - Installing DNX Runtime Versions

If you just installed DNVM fresh, or if you want to get the latest version of a particular DNX implementation, we can use the the dnvm install command with some appropriate arguments:

By default, DNVM will work with the basic .NET framework, and assume the x86 architecture. For example, if we do the following:

DNVM Install Latest:
> dnvm install latest

 

DNVM will download and install the latest stable version of the regular .NET framework for the x86 architecture. If we run dnvm list again, we see the following:

Installed DNX Runtimes after Running DNVM Install Latest:

run-dnvm-install-latest-noargs

If we want to specify a different runtime (say, the CoreCLR instead of the .NET Framework, and/or specify the x64 version, we need to add the -r ( -runtime ) and/or -arch ( -architecture ) flags, and values:

DNVM Install Latest for Specific Runtime/Architecture:
> dnvm install latest -r coreclr -arch x64

 

Once the above is finished running, we have now added the latest version of the full .NET Framework for the x86 architecture, and CoreCLR for the x64 architecture to our available runtimes list:

Installed DNX Runtimes:

run-dnvm-list-after-install

DNVM Upgrade VS. DNVM install

DNVM also has an upgrade command, which behaves just a little differently than Install.

DNVM Install fetches the specified version, and makes it active in the current Command process by adding it to the process PATH variable. The selection is "Active" is only for the duration of our terminal session. Once the current terminal session is closed, the active selection will revert to none, or whatever had been previously persisted in our User PATH variable as the default.

DNVM Upgrade does essentially the same thing, but also adds it to the User's PATH variable as the default active version, and updates the default alias. For example, if we used dnvm upgrade to install the latest 64 bit version of the .NET framework clr:

Upgrade .NET Framework CLR to Latest Version Using DNVM Upgrade:
> dnvm upgrade -r clr -arch x64

 

After running the above, our Console output tells us that the latest version of dnx-clr-win-x64 has been added not only to the current process PATH, but also to our User PATH. In addition, the "default" alias has been updated to point to the just-installed version:

Console Output from DNVM Upgrade:

dnvm-upgrade

Note that dnvm upgrade pulls down the latest stable release from Nuget. If you want to work on the bleeding edge with the latest unstable (development) release, you can use:

Upgrading to Latest Unstable (development) Runtime Releases:
> dnvm upgrade -u

 

In the above, you can specify runtime/architecture as previously using the -r and -arch flags.

5/17/2015 - NOTE: If you installed Visual Studio 2015, the system environment PATH variable likely points to C:\Program Files\Microsoft DNX\Dnvm\. As of this writing, the Visual Studio version of DNVM does not recognize the -u (-unstable ) flags. Even if you installed DNVM using the shell scripts at the beginning of this article, the Visual Studio variable will be found first. In order to use the -u flag, you will need to either change the order in which the PATH variables occur, or remove the Visual Studio PATH and add DNVM using one of the scripts above.

Working with DNVM - Selecting or Changing the Active DNX Runtime

Notice in the previous section the asterisk that appears in the "Active" column of the console output once we started installing new DNX runtime versions. When we use dnvm Install, DNVM makes the just-installed version the default active version for the current process (in other words, for the current terminal session only).

As noted previously, when we run dnvm upgrade, DNVM makes the just-installed version the default active version not only for the current process, but also at the User level.

We can switch to a different DNX runtime by using the dnvm use command. By default, dnvm use changes the active selection for the current Command process. For example, given the current active runtime in the console output from the previous section (1.0.0-beta4-11566 clr x64), we could decide we want to switch to the latest 64 bit coreclr version for our current terminal session instead:

Select or Switch to a Different Runtime for the Current Process:
> dnvm use 1.0.0-beta4-11566 -r coreclr -arch x64

 

If we run the above command, and then run dnvm list again, we see our active version has changed:

New Active DNX Runtime Selected for Current Process:

switch-dnx-version-for-process-path

If we look closely at the console output above though, we see that the new version was added to the process PATH, meaning, the selection will persist for the current Console process only. If we close the console window, and open another, the default set in our User PATH will be selected again.

If we want to set our user default, we could run the command just like we did previously, but instead we can add the -p ( -persistent) flag, which will cause the selection to be added to our user path instead of the process path:

Select or Switch to a New DNX Runtime Default for User PATH:
> dnvm use 1.0.0-beta4-11566 -r coreclr -arch x64 -p

 

Now, our selection will persist as the default between Command sessions. We can still select a different version per process just like we did previously, but until we make additional changes, the default active DNX runtime in a Command session will be the beta 4 CoreCLR from build 11566.

Remove Runtime References from PATH Variables

If we want to remove all runtime references from the process path (in other words, return to a state where no runtime is set as "Active" we can run:

Remove DNX Runtime References from Process PATH Variable:
> dnvm use none

 

If we want to remove any defaults we have set in our User PATH variable, we can add the -p flag:

Remove DNX Runtime References from User PATH Variable:
> dnvm use none -p

 

Use Aliases to Make Typing Easier

If you have been working through the examples so far, you may have noticed how painful it can be typing out the full, semantic version names each time you want to refer to a runtime version. DNVM affords us the ability to assign aliases to the different installed versions. We can do this during install or upgrade using the -a ( -alias ) flag, or we can set aliases for existing installed versions using the alias command.

For example, we already have an alias, default, which in my case was set up when I installed Visual Studio. It was originally assigned to the regular x86 .NET framework CLR, and then was re-assigned when we ran dnvm upgrade in the previous section. As of now, the alias default on my machine points to the latest (build 11566) x64 bit version of the .NET CLR.

I can set an alias for the latest x64 version of CoreCLR like so:

Assign an Alias to a DNX Runtime:
> dnvm alias core-64-latest 1.0.0-beta4-11566 -r coreclr -arch x64

 

Having done that, I can now refer to that particular runtime by its alias, for example:

Select or Switch to a new DNX Runtime Using an Alias:
> dnvm use core-64-latest

 

5/17/2015 - NOTE: There is currently a bug (see issue #175 / PR #248 at the DNVM Repo on Github) in which referring to a CoreClr runtime by alias does not work. As of this writing, the PR has not yet been merged, but things are supposed to work as described here. Until the issue is resolved, it is still necessary to refer to any CoreClr runtime by its full version name…

We can re-assign a previously set alias by simply using the dnvm alias command, and assigning the alias to a different DNX Runtime.

DNX and DNU - Working with an Example Project from the Command Line

To get a feel for how DNVM, DNU, and DNX work together, we'll put together a very basic example project, using only the Windows Command Prompt and a text editor (for this post, I'm going to use Sublime Text 3, but we could just as easily use Visual Studio Code, or Notepad).

First, let's create a project directory, and then open the folder in Sublime Text:

Create a Project Directory and Navigate into the Directory using CMD:
C:\Users\John> mkdir dnx_demo
C:\Users\John> cd dnx_demo

 

Then, open the directory folder in Sublime text. First, we'll add a project.json file:

Add project.json File:
{
  "version": "1.0.0-*",
  "description": "Silly demo project",
  "commands": {
    "runme": "dnx_demo"
  },
  "frameworks": {
    "dnx451": { },
    "dnxcore50": {
      "dependencies": {
        "System.Console": "4.0.0-beta-22816",
        "Microsoft.CSharp": "4.0.0-beta-22816"
      }
    }
  }
}

 

In the above, note we have defined a command, "runme" which refers to the project name. We can invoke this command from the Command Line using dnx to run our project. Also note, we have specified both the traditional .NET Framework (dnx451) as well as the .NET Core (dnxcore50) as compilation targets, so our application wioll be cross-compiled for both DNX runtimes and frameworks.

Next, add a file named Program.cs and paste in the following code:

The Program.cs File:
using System;
namespace dnx_demo
{
    public class Program
    {
        public void Main(string[] args)
        {
            Console.WriteLine("No Visual Studio Here!!");
            Console.Read();
        }
    }
}

 

By simply adding these two files, we have (almost) everything we need to run a very basic, but complete, .NET Console application. Save the two files above, and return to the Command prompt.

Use DNU Restore to Restore Packages

Our project.json file specifies the target frameworks and dependencies our project requires. Note that for this project, there are no packages to be pulled down when we run against the standard .NET framework 4.5.1 - the required references are already present in the .NET framework itself.

We will need to restore packages before we can run against the .NET Core framework and CoreCLR. Remember, .NET Core is all about "pay as you go." In other words, We pull in only those libraries we need for our application to run, and leave out everything else.

We can restore library packages by simply running dnu restore from within our project directory:

Use DNU Restore to Restore Library Package Dependencies:
C:\Users\John\dnx_demo> dnu restore

 

Run the Example Application Using DNX

With our package dependencies restored, we can run our application using DNX. We can now run the application, after we select which DNX runtime we want to use.

In my case, we set the default active runtime to the latest .NET Core CLR / x64 in a previous example, so we can run the application straight away from within our project directory:

Run the Example Application Using DNX:
C:\Users\John\dnx_demo> dnx . runme

 

Take a close look there. Since I am already in the project directory, I can simply type dnx, and use a period to indicate the current directory. DNX will parse the command, runme, we set up in our project.json file, and use that to run the project.

dnx-run-example-using-command

We could also simply reference the project by name:

Run the Example by Referencing the Project Directory Name:
C:\Users\John\dnx_demo> dnx . dnx_demo

 

Or, as long as we are in the project directory, we could keep it REAL SIMPLE and just use dnx . run

Run the Example Using dnx . run:
C:\Users\John\dnx_demo> dnx . run

 

Now, let's switch runtimes from .NET Core to the traditional .NET Framework. Recall, we had previously used dnvm upgrade to install the latest x64 binaries for the .NET framework, and when we did that, our default alias was assigned to that runtime:

Switch to the .NET Framework Runtime Using DNVM Use:
C:\Users\John\dnx_demo> dnvm use default

We can check to make sure we are now targeting the .NET CLR instead of CoreCLR, and then run our application again:

Running the Example Using the .NET Framework and Standard CLR:

dnx-run-example-using-clr

 

Summing Up

So far, we've examined the basics of using the .NET Version Manager, the .NET Development Utility (DNU), and the .NET Execution Environment in order to get a basic application up and running in the new ASP.NET environment.

In our simple example above, we compiled and executed our project in memory. There is no generation of binaries as part of the dnx run process. DNX, and DNU offer a wealth of additional features, such outputting binaries as a part of the build process (dnu build), creating Nuget packages (dnu pack) and other useful commands.

DNU, DNX, and DNVM are currently in active development, and things are changing daily. Keep your eye on the ASP.NET 5 repo, and watch for updates here and elsewhere.

We will explore more in upcoming posts

Additional Resources and Items of Interest

 

Posted on May 17 2015 08:13 PM by jatten     

Comments (6)

ASP.NET Web API: Understanding OWIN/Katana Authentication/Authorization Part III: Adding Identity

Posted on February 15 2015 06:19 PM by jatten in ASP.NET MVC, ASP.Net, C#, CodeProject   ||   Comments (7)

eyball-500This is the third post in a series in which we have built up a minimal, self-hosted, OWIN-based Web Api application essentially from scratch. Our objective has been to develop a better understanding of how the various components fir together and interact in an OWIN-based environment, and to do so without creating any dependencies on IIS or the heavy weight System.Web.dll.

Up to this point, we have created a basic Web Api, and implemented our own authentication/authorization, using basic OWIN authorization, and our own set of models. What we have built so far represents a bare-bones model of how authentication and authorization work in an OWIN-based application. We have taken some architectural shortcuts in the name of maintaining a simple, easy to understand structure as again, our goal so far has emphasized concept over details.

Image by alles-schlumpf  |  Some Rights Reserved

Previous posts, in order:

In this post, we are going pull in the ASP.NET Identity framework, and ideally, we will again achieve a better understanding of how Identity fits in to a general Web Api application, and we will allow Identity to perform some of the heavy lifting for us when it comes to difficult, hard-to-get-right-even-for-the-experts details such as crypto and security details.

Source Code for Examples

We are building up a project over a series of posts here. In order that the source for each post make sense, I am setting up branches that illustrate the concepts for each post:

On Github, the branches of the Web Api repo so far look like this:

  • Branch: Master - Always the most current, includes all changes
  • Branch: auth-db - The code we build up in the course of the previous post, adding a persistence layer for our authentication system.
  • Branch: auth-identity - the code we will build out in the course of this post. We will start where we left off in the previous post, and modify to bring in a minimal implementation using Identity Framework.

The code for the API client application is in a different repo, and the branches look like this:

  • Branch: Master - Always the most current, includes all changes
  • Branch: owin-auth - Added async methods, and token-based authentication calls to the Web Api application. The code for the client application remains unchanged, except when we need to switch out user credentials.

In the previous article, we created create the classes MyUser and MyUserClaim classes in order to implement our authorization and authentication mechanism in the OWIN/Katana environment, and which also became our code-first models for database persistence via Entity Framework. We also created the MyUserStore class, which contained the methods necessary to save and retreive user authentication data from our backing store.

We had assembled these very rudimentary classes into a functioning authentication and authorization framework of sorts, using them in our application to perform the basic functions needed to properly authenticate a user, and establish a minimal authorization mechanism based upon the role claims possessed by each user.

In this post, we are going to use ASP.NET Identity instead, and replace our crude, homebuilt mechanism with a fully-functioning, if basic, auth system.

Core Identity Framework

To understand how Identity will fit into our application, and the OWIN/Katana environment, it is useful to examine the structure of Identity framework itself.

The actual core Identity library is Microsoft.AspNet.Identity.Core. This library defines a host of interfaces upon which the function of Identity is based, and a smaller number of concrete implementation classes which are expressed in terms of these interfaces. We actually already have this library in our project, because we pulled in the Microsoft.AspNet.Identity.Owin library previously via Nuget. We haven't used any of the identity components to this point, but we made use of some items from dependent libraries included in that Nuget package, such as Microsoft.Owin.Security and Microsoft.Owin.OAuth

In general, the models which might need to be consumed in an application are expressed as interfaces, and the internals of the framework provide implementation for those interfaces. It is up to the application, and/or any other frameworks pulled in, to provide the concrete implementations for these model interfaces.

For example, the core Identity framework provides us with a pair of interfaces to represent a User:

Two Versions of the IUser Interface:
// Interface with generic type argument for the Key:
public interface IUser<out TKey>
{
    TKey Id
    {
        get;
    }
 
    string UserName
    {
        get;
        set;
    }
}
// Interface derived from IUser<Tkey> Specifying string Key:
public interface IUser : IUser<string> { }

 

In a similar manner, most of the interfaces defined in the core Identity framework to represent persistence models are expressed in a manner which allows us to specify the type for the key to be used.

Additionally, many of the Identity interfaces are dependent on other interfaces in the framework. In these cases, the interface is expressed in terms of a generic type argument representing the concrete implementation of the dependency. For example, core Identity framework provides two interfaces to represent a UserStore:

Two Versions of the IUserStore Interface:
// Interface with generic type arguments for User, and the User Key:
public interface IUserStore<TUser, in TKey> : IDisposable
where TUser : class, IUser<TKey>
{
    Task CreateAsync(TUser user);
    Task DeleteAsync(TUser user);
    Task<TUser> FindByIdAsync(TKey userId);
    Task<TUser> FindByNameAsync(string userName);
    Task UpdateAsync(TUser user);
}
// Interface expressing IUserStore in terms of generic User type, 
// and specifying a string User Key
public interface IUserStore<TUser> : IUserStore<TUser, string>, IDisposable
where TUser : class, IUser<string>
{
}

 

If you explore the Microsoft.AspNet.Identity.Core library using a free tool such as Telerik's fine Just Decompile, you can explore the various interfaces and concrete classes available, and develop an understanding of how they relate. However, a quick look using even the VS Object Browser will reveal that there are no concrete implementations of the basic model interfaces we need in order to implement Identity in our application. For this, we either need to roll our own, or pull in another library which provides ready-to-use implementations.

Since we are already using Entity Framework, in our case this is easy.

Identity and Entity Framework

The Microsoft.AspNet.Identity.EntityFramework library provides concrete implementation classes needed to use Identity from an application using Entity Framework. In this library we find some model classes we can use as-is, or which we can extend and customize as needed. For example, the IdentityUser class provides a concrete implementation for IUser<Tkey> :

The Base IdentityUser Class:
// Base implements IUser<TKey> and is expressed with generic type arguments
// for other model types required by Identity Framework:
public class IdentityUser<TKey, TLogin, TRole, TClaim> : IUser<TKey>
    where TLogin : IdentityUserLogin<TKey>
    where TRole : IdentityUserRole<TKey>
    where TClaim : IdentityUserClaim<TKey>
{
    public IdentityUser()
    {
        this.Claims = new List<TClaim>();
        this.Roles = new List<TRole>();
        this.Logins = new List<TLogin>();
    }
 
    public virtual TKey Id { get; set; }
    public virtual string UserName { get; set; }
    public virtual string Email { get; set; }
    public virtual bool EmailConfirmed { get; set; }
    public virtual string PhoneNumber { get; set; }
    public virtual bool PhoneNumberConfirmed { get; set; }
 
    public virtual string SecurityStamp { get; set; }
    public virtual bool TwoFactorEnabled { get; set; }
    public virtual string PasswordHash { get; set; }
 
    public virtual int AccessFailedCount { get; set; }
    public virtual bool LockoutEnabled { get; set; }
    public virtual DateTime? LockoutEndDateUtc { get; set; }
 
    public ICollection<TLogin> Logins { get; set; }
    public ICollection<TRole> Roles { get; set; }
    public ICollection<TClaim> Claims { get; set; }
}
 
 
// Alternate implementation derives from Generic implementation, 
// and expresses Generic model types in terms of classes defined 
// within Identity.EntityFrameowrk Library: 
public class IdentityUser : IdentityUser<string, IdentityUserLogin, 
    IdentityUserRole, IdentityUserClaim>, IUser, IUser<string>
{
    public IdentityUser()
    {
        this.Id = Guid.NewGuid().ToString();
    }
 
    public IdentityUser(string userName) : this()
    {
        this.UserName = userName;
    }
}

 

We can see in the above example that there is a lot of functionality ready to go in the basic IdentityUser implementation. Also, note that the various generic type arguments provided in the base implementation are again provided such that we might extend our Identity model classes with custom implementations, for example, if we wanted to use integer keys instead of strings.

The Identity.EntityFramework library provides similar implementations for the other interfaces defined in Identity.Core. In addition, as we might expect, Identity.EntityFramework also includes the IdentityDbContext class, which knits together the various model classes, ready for use in a EF/Code-First application.

What is important here is understanding that the Identity.Core library provides the interfaces we need, and implements the interactions between those interfaces. It is up to us to provide the implementation for those interfaces, either by rolling our own, or by using a library specific to our persistence model such as Identity.EntityFramework.

Add Identity.EntityFramework Library Via Nuget

Since we are using Entity Framework in our minimal OWIN Web Api project, we will pull in the Identity.EntityFramework package we discussed above to take advantage of the ready-made Identity implementation afforded by the Identity team.

NOTE: This post assumes you are working with ASP.NET < 5.0, and Identity 2.1. As of this publication date, the newest package for this library is a pre-release of Identity 3.0 which targets ASP.NET 5. Unless you are working with ASP.NET 5.0 ("vNext") you want to make sure you are pulling in version 2.1

Add the Microsoft.AspNet.Identity.EntityFramework Nuget Package:
PM> Install-Package Microsoft.AspNet.Identity.EntityFramework -Version 2.1.0

 

We already have the Identity.Core library in our example project, because it was included when we pulled in the Identity.Owin Nuget package in Part I of this series.

Add Identity to the Self-Hosted Web Api - Models and Stores

To get started, we will be picking up where we left off in the previous post. Recall that we had added an AuthModels.cs file, and coded up a MyUser class, a MyUserClaim class, a MyPasswordHasher class, and a MyUserStore class.

We can get rid of all that now, delete the AuthModels.cs file.

In order to add the (mostly) ready-to-use Identity framework to our project, let's add a new code file named IdentityModels.cs, and add the following code:

Add Identity Models:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add using statements:
using Microsoft.Owin;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.AspNet.Identity.EntityFramework;
 
namespace MinimalOwinWebApiSelfHost.Models
{
    public class ApplicationUser : IdentityUser
    {
        // A default Constructor:
        public ApplicationUser() { }
        
        public ApplicationUser(string email) : base(email)
        {
            // Use the email for both user name AND email:
            UserName = email;
        }
    }
 
 
    public class ApplicationUserManager 
        : UserManager<ApplicationUser>
    {
        public ApplicationUserManager(IUserStore<ApplicationUser> store) 
            : base(store) { }
 
 
        public static ApplicationUserManager Create(
            IdentityFactoryOptions<ApplicationUserManager> options,
            IOwinContext context)
        {
            return new ApplicationUserManager(
                new UserStore<ApplicationUser>(
                    context.Get<ApplicationDbContext>()));
        }
    }
}

 

Now, let's take a good hard look at what's going on in the above code.

First, we have added an ApplicationUser class, which derives from IdentityUser. IdentityUser is a concrete implementation if the Identity.Core IUser interface, and is provided by the Identity.EntityFramework library we discussed previously. We aren't doing much in this derived class at this point, but we will be adding to it later.

Next, we have the ApplicationUserManager class, which derives from UserManager. Unlike IdentityUser, the UserManager class is a part of the Identity.Core library. In other words, any application using the Identity framework can expect to have access to UserManager, or a derivation similar to what we have done above.

Notice that our ApplicationUserManager expects an argument of IUserStore as a constructor parameter. What's this?

We'll take a short detour to discuss UserManager and UserStore, and the purpose behind each.

UserManager and UserStore - What's the Difference?

The core Identity framework defines the UserManager class to implement various functionality required to, well, manage user information according to business rules and configuration established either by Identity framework itself, or as part of configuration options set up during development.

These framework "rules" and configuration items are independent of the specific persistence store used to save and retrieve the user identity data. In other words, the UserManager understands and works with Identity model objects, without concern for the concrete database underlying the application.

Examples of the sorts of functionality afforded by UserManager include methods such as:

  • CreateAsync(TUser user, string Password)
  • AddToRoleAsync(TKey userId, string role)
  • AddClaimAsync(Tkey userId, Claim claim)

The UserManager class is defined in terms of various interfaces which represent abstractions over database-specific implementation models. As an example, the basic UserManager is defined with a generic type argument for the IUser implementation, which must be specified. The UserManager class also requires a constructor argument which implements the IUserStore interface.

A concrete implementation of IUserStore represents the underlying persistence layer of the application. In other words, a UserStore implementation knows how to "talk" to a specific data store (such as MongoDb, SQL Server, RavenDb, Etc.).

In our code, we are using the default UserStore implementation provided by EntityFramework (which is, itself, an abstraction over our SQL CE or SQL Server database…).

The idea behind defining a UserManager base class in Identity.Core in terms of an interface IUserStore is to achieve a clean separation between the business rules governing how authentication and authorization occurs between Identity model objects, and the details of the application's specific backing store.

Within out application proper, when we use Identity we should generally be using the UserManager (or a derived version of it) the work directly with our identity model objects. We rarely have need to consume an instance of UserStore directly, except for the purpose of injecting it as a constructor argument to UserManager.

UserManager, UserStore, and Identity:

usermanager-userstore

Also notice in our code, we have added a static method, Create(). We'll discuss this momentarily as well. But first, we will update the code for our database context.

Update the DbContext to Inherit from IdentityDbContext

When we finished the last article in this series, we had updated our ApplicationDbContext code file to look like this:

The Previous DbContext:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add using:
using System.Data.Entity;
using System.Security.Claims;
 
namespace MinimalOwinWebApiSelfHost.Models
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext()
            : base("MyDatabase")
        {
 
        }
 
        static ApplicationDbContext()
        {
            Database.SetInitializer(new ApplicationDbInitializer());
        }
 
        public IDbSet<Company> Companies { get; set; }
        public IDbSet<MyUser> Users { get; set; }
        public IDbSet<MyUserClaim> Claims { get; set; }
    }
 
 
    public class ApplicationDbInitializer 
        : DropCreateDatabaseAlways<ApplicationDbContext>
    {
        protected async override void Seed(ApplicationDbContext context)
        {
            context.Companies.Add(new Company { Name = "Microsoft" });
            context.Companies.Add(new Company { Name = "Apple" });
            context.Companies.Add(new Company { Name = "Google" });
            context.SaveChanges();
 
            // Set up two initial users with different role claims:
            var john = new MyUser { Email = "john@example.com" };
            var jimi = new MyUser { Email = "jimi@Example.com" };
 
            john.Claims.Add(new MyUserClaim 
            { 
                ClaimType = ClaimTypes.Name, 
                UserId = john.Id, 
                ClaimValue = john.Email 
            });
            john.Claims.Add(new MyUserClaim 
            { 
                ClaimType = ClaimTypes.Role, 
                UserId = john.Id, 
                ClaimValue = "Admin" 
            });
 
            jimi.Claims.Add(new MyUserClaim 
            { 
                ClaimType = ClaimTypes.Name, 
                UserId = jimi.Id, 
                ClaimValue = jimi.Email 
            });
            jimi.Claims.Add(new MyUserClaim 
            { 
                ClaimType = ClaimTypes.Role, 
                UserId = john.Id, 
                ClaimValue = "User" 
            });
 
            var store = new MyUserStore(context);
            await store.AddUserAsync(john, "JohnsPassword");
            await store.AddUserAsync(jimi, "JimisPassword");
        }
    }
}

 

In the same code file, we had defined both our ApplicationDbContext, and a database initializer.

Now that we have access to the Identity.Core and Identity.EntityFramework libraries, we can simplify this somewhat.

First of all, Identity.EntityFramework provides us with IdentityDbContext, which, as its name implies, is an Identity-specific implementation of the DbContext. There is a little more going on under the hood than we will cover here, but essentially, IdentityDbContext provides us with a base class from which we can inherit, and which provides a DbContext implementation which works with the base Identity.EntityFramework models we will be working with.

First, we are going to modify the code for our ApplicationDbContext above to derive from IdentityDbContext. Then, we will update the ApplicationDbInitializer to work with our new DbContext and Identity models.

Modify DbContext to Derive from IdentityDbContext:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add using:
using System.Data.Entity;
using System.Security.Claims;
 
// Add THESE to use Identity and Entity Framework:
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
 
namespace MinimalOwinWebApiSelfHost.Models
{
    // Derive from IdentityDbContext:
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("MyDatabase") { }
 
 
        static ApplicationDbContext()
        {
            Database.SetInitializer(
                new ApplicationDbInitializer());
        }
 
 
        // Add a static Create() method:
        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
 
 
        // We still need a DbSet for our Companies 
        // (and any other domain objects):
        public IDbSet<Company> Companies { get; set; }
    }
 
 
    public class ApplicationDbInitializer 
        : DropCreateDatabaseAlways<ApplicationDbContext>
    {
        protected async override void Seed(ApplicationDbContext context)
        {
            context.Companies.Add(new Company { Name = "Microsoft" });
            context.Companies.Add(new Company { Name = "Apple" });
            context.Companies.Add(new Company { Name = "Google" });
            context.SaveChanges();
 
            // Set up two initial users with different role claims:
            var john = new ApplicationUser 
            { 
                Email = "john@example.com", 
                UserName = "john@example.com" 
            };
            var jimi = new ApplicationUser 
            { 
                Email = "jimi@Example.com", 
                UserName = "jimi@example.com" 
            };
 
            // Introducing...the UserManager:
            var manager = new UserManager<ApplicationUser>(
                new UserStore<ApplicationUser>(context));
 
            var result1 = await manager.CreateAsync(john, "JohnsPassword");
            var result2 = await manager.CreateAsync(jimi, "JimisPassword");
 
            // Add claims for user #1:
            await manager.AddClaimAsync(john.Id, 
                new Claim(ClaimTypes.Name, "john@example.com"));
 
            await manager.AddClaimAsync(john.Id, 
                new Claim(ClaimTypes.Role, "Admin"));
 
            // Add claims for User #2:
            await manager.AddClaimAsync(jimi.Id, 
                new Claim(ClaimTypes.Name, "jimi@example.com"));
 
            await manager.AddClaimAsync(jimi.Id, 
                new Claim(ClaimTypes.Role, "User"));
        }
    }
}

 

In the above code, notice that we have now implemented our ApplicationDbContext by deriving from IdentityDbContext<ApplicationUser> . In so doing, we have specified a DbContext implementation which will be ready to use, and already work with our ApplicationUser class.

We have also updated our ApplicationDbInitializer, making use of the handy interface afforded by our ApplicationUserManager to easily add our test users, and related user claims.

Pay close attention here. Remember previously, how we went ahead and create a mock password hasher, and all that nonsense about implementing a proper crypto mechanism for hashing passwords? here, Identity has taken care of all that for us. No mocking needed. Just the way we like it, we have left the details of the crypto to folks who know what they are doing. Remember, crypto is hard, even for the experts, and it is a solved problem.

Now, before we go much further, we are going to take another short detour. Notice how, like we did with ApplicationUserManager, we also defined a static Create() method on our ApplicationDbContext? We're going to take a look at why we did that now.

Context per Request and CreatePerOwinContext

From the standpoint of our data model, we want to make sure that we are always working with the same instance of our database context, and hence, with the same set of objects. For example, if two separate instances of ApplicationDbContext (or, similarly, UserStore or UserManager) are created while processing the same HTTP request, it is possible we could introduce changes to two instances of the same  user data.

We want to make sure that when we retreive a user object, it will always refer to the same instance of that user's data within the context of a single HTTP request.

The Microsoft.AspNet.Identity.Owin library provides an extension method by which we can ensure a single instance of an object is created per OwinContext. The CreatePerOwinContext() method allows us to pass in a generic type argument, and a function reference which returns an instance of the desired object. We set this up during the Owin Configuration() method. Then, when the OwinContext object is created for each incoming HTTP request, a discreet instance of the desired object will be created per OWIN context.

For a deeper look at this concept, see Per request lifetime management for UserManager class in ASP.NET Identity

In our application, we want to make sure that during request processing, we are only ever working against the same instance of ApplicationDbContext, as well as ApplicationUserManager. We achieve this by adding those state Create() methods on ApplicationDbContext and ApplicationUserManager respectively, and then passing references to them to CreatePerOwinContext() during the Owin Configuration() method.

We will want to add the following code to our ConfigureAuth() method in our Startup class:

Create ApplicationDbContext and ApplicationUserManager per Owin Context:
private void ConfigureAuth(IAppBuilder app)
{
    // Create per OWIN Context:
    app.CreatePerOwinContext<ApplicationDbContext>(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
 
    var OAuthOptions = new OAuthAuthorizationServerOptions
    {
        TokenEndpointPath = new PathString("/Token"),
        Provider = new ApplicationOAuthServerProvider(),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
 
        // Only do this for demo!!
        AllowInsecureHttp = true
    };
    app.UseOAuthAuthorizationServer(OAuthOptions);
    app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

 

Recall from our previous explorations of OWIN and Katana that when we pass function references like this, the function itself is not executed at this point in our code. Instead, a reference to the function is added to the Owin Environment Dictionary, which will then be Invoked each time a new Owin context is created in response to an incoming HTTP request.

We can see some of the logic to all this if we take a closer look at the static Create() method we defined on our ApplicationUserManager class:

The Create() Method from ApplicationUserManager:
public static ApplicationUserManager Create(
    IdentityFactoryOptions<ApplicationUserManager> options,
    IOwinContext context)
{
    return new ApplicationUserManager(
        new UserStore<ApplicationUser>(
            context.Get<ApplicationDbContext>()));
}

 

Notice how even here, we are initializing an instance of UserStore and passing in a reference to ApplicationDbContext by retrieving it from the OwinContext instance? This way we ensure that even here, we are using the single DbContext object instance created specifically for each request.

Update OAuth Server Provider for Identity

Now that we have implemented a very basic Identity model, we can modify our ApplicationOauthServerProvider. In the call to GrantResourceOwnerCredentials(), we can avail ourselves of our ApplicationUserManager and Identity models to simplify the grant process.

Add Microsoft.AspNet.Identity.Owin to the using statements at the top of the file, and then replace the existing code as follows:

Update the code for GrantResourceOwnerCredentials for Identity:
using System.Threading.Tasks;
 
// Add Usings:
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using System.Security.Claims;
using MinimalOwinWebApiSelfHost.Models;
 
// Add to use Identity:
using Microsoft.AspNet.Identity.Owin;
 
namespace MinimalOwinWebApiSelfHost.OAuthServerProvider
{
    public class ApplicationOAuthServerProvider 
        : OAuthAuthorizationServerProvider
    {
        public override async Task ValidateClientAuthentication(
            OAuthValidateClientAuthenticationContext context)
        {
            // This call is required...
            // but we're not using client authentication, so validate and move on...
            await Task.FromResult(context.Validated());
        }
 
 
        public override async Task GrantResourceOwnerCredentials(
            OAuthGrantResourceOwnerCredentialsContext context)
        {
            // ** Use extension method to get a reference 
            // to the user manager from the Owin Context:
            var manager = context.OwinContext.GetUserManager<ApplicationUserManager>();
 
            // UserManager allows us to retrieve use with name/password combo:
            var user = await manager.FindAsync(context.UserName, context.Password);
            if (user == null)
            {
                context.SetError(
                    "invalid_grant", "The user name or password is incorrect.");
                context.Rejected();
                return;
            }
 
            // Add claims associated with this user to the ClaimsIdentity object:
            var identity = new ClaimsIdentity(context.Options.AuthenticationType);
            foreach (var userClaim in user.Claims)
            {
                identity.AddClaim(new Claim(userClaim.ClaimType, userClaim.ClaimValue));
            }
 
            context.Validated(identity);
        }
    }
}

 

Once again, see in the above how we made sure to grab a reference to the ApplicationUserManager instance from the context object? The context object helpfully provides a GetUserManager() extension method.

Also note how the ApplicationUserManager makes it very convenient to retrieve a user object with a user name and password. If the password fails to match, null will be returned, and the invalid grant error returned.

Update the CompaniesController to Use the DbContext per Request

We don't HAVE to do this, but we can. We might update our CompaniesController to take advantage of the Context-per-Request strategy afforded by Identity here.

Make sure to add Microsoft.AspNet.Identity.Owin to the using statements at the top of the CompaniesController file.

Update CompaniesController to Use Context per Request:
public class CompaniesController : ApiController
{
    // Ditch THIS:
    //ApplicationDbContext dbContext = new ApplicationDbContext();
 
    // Replace with something like THIS:
    ApplicationDbContext dbContext
    {
        get
        {
            return Request.GetOwinContext().Get<ApplicationDbContext>();
        }
    }
 
    ... All the rest of the controller code....
 
}

 

With that, we can give our new and improved application a test run, using the same Api Client application from our previous post.

Running the Application with Identity in Place

If we spin up our Web Api, all should look well:

Running the Web Api Application - All is Well:

run-web-api-application

Next, if we run the API Client application, making sure we use our valid user credentials (they should match the credentials for the Admin user in the Seed() method), everything should work as before:

Running the API Client Application:

run-api-client-application-with-identity

Similarly, if we modify the code in our client application and pass an invalid password, we get an invalid grant error:

Invalid Password Submitted by Client Returns Invalid Grant Error:

run-api-client-application-with-identity-invalid-grant

And, if we change the client credentials to those of the user in the plain old User role (which does NOT have authorization to access our CompaniesController), we receive a 401/Unauthorized error:

API Client with Insufficient Authorization:

run-api-client-application-with-identity-unauthorized

Summing it Up

In the course of the last four articles, we have hopefully developed a better idea of how the pieces fit together in an OWIN-based Web Api application. The lines between the various frameworks become blurry as an application grows, and my objective was to break things down in a manner that would bring some clarity to what happens where, and why.

The structure of our example application is crude, and if you were to take this a few steps further, you would definitely want to change some things, do some refactoring, and implement a great deal more exception and error handling.

Similarly, our console-based API Client application is sufficient only to the task of exercising our Web Api for demonstration purposes.

From here, we could go a long ways further in developing a claims-based authorization model. As it stands, our little sample application does use claims, but relies on the in-build ability of [Authorize] attribute to perform a role-based authorization check. We will explore claims more extensively in an upcoming post.

As always, feedback is most welcome, especially if you noticed me doing something stupid, or find outright errors in the code. Pull Requests are welcome against the sample repo, so long as they address improvements or bug fixes. For obvious reasons, I want to keep the code samples in sync with the articles.

Additional Resources and Items of Interest

 

Posted on February 15 2015 06:19 PM by jatten     

Comments (7)

ASP.NET Web Api: Understanding OWIN/Katana Authentication/Authorization Part I: Concepts

Posted on January 19 2015 12:45 PM by jatten in ASP.NET MVC, ASP.Net, C#, CodeProject   ||   Comments (3)

Ah-aint-long-for-this-whorl-240Recently we looked at the fundamentals of the OWIN/Katana Middleware pipeline, and we then applied what we learned, and built out a minimal, OWIN-Based, self-hosted Web Api. In doing so, we managed to avoid the heavy weight of the System.Web library or IIS, and we ended up with a pretty lightweight application. However, all of the concepts we have discussed remain valid no matter the hosting environment.

But what if we want to add some basic authentication to such a minimal project?

Image by Chad Miller  | Some Rights Reserved

Once again, we are going to see if we can't apply what we've learned, and pull a very small Authentication / Authorization component into our minimal Web Api application. We'll start by implementing a basic authentication/authorization model without using the components provided by the ASP.NET Identity framework.

Identity is fully compatible with the OWIN Authorization model, and when used in this manner, represents a very useful, ready-to go concrete implementation. But we can perhaps better understand the structure of OWIN authorization, and application security in general, if we start with simple concepts, and work our way up to concrete implementations and additional frameworks.

From the Ground Up

In this series of posts we will start with concepts, and slowly build from there.

  • Part I (this post) - We will examine the basic OAuth Resource Owner Flow model for authentication, and assemble to most basic components we need to implement authentication using this model. We will not be concerning ourselves with the cryptographic requirements of properly hashing passwords, or persisting user information to a database. We will also not be using Identity, instead implementing security using the basic components available in the Microsoft.Owin libraries.
  • Part II - We will mock up some basic classes needed to model our user data, and a persistence model to see how storage of user data and other elements works at a fundamental level.
  • Part III - We will replace our mock objects with Identity 2.0 components to provide the crypto and security features (because rolling your own crypto is not a good idea).

As with our previous posts, the objective here is as much about building an understanding of how authentication in general, and Identity 2.0 in particular, actually fit in to the structure of an OWIN-based application as it is about simply "how to do it."

With that in mind, we will take this as far as we reasonably can using only the OWIN/Katana authorization components and simplified examples. Once we have seen the underlying structure for authentication and authorization in an OWIN-based  Web Api application, THEN we will bring Identity 2.0 in to provide the concrete implementation.

Source Code for Examples

We are building up a project over a series of posts here. In order that the source for each post make sense, I am setting up branches that illustrate each concept:

On Github, the branches of the Web Api repo so far look like this:

The code for the API client application is in a different repo, and the branches look like this:

Application Security is Hard - Don't Roll Your Own!

Implementing effective application security is a non-trivial exercise. Behind the simple-looking framework APIs we use, such as Identity 2.0 (or any other membership/auth library) is a few decades worth of development by the best and brightest minds in the industry.

Throughout the examples we will be looking at, you will see areas where we mock together some ridiculous methods of (for example) hashing or validating passwords. In reality, securely hashing passwords is a complex, but solved problem. You should never attempt to write your own crypto or data protection schemes.

Even a simple authentication mechanism such as we will implement here brings some complexity to the project, because authentication itself is inherently complex. Behind the simple-seeming framework API provided by frameworks such as ASP.NET Identity lies some crypto and logic that is best left as it is unless you REALLY know what you're doing.

That said, understanding how the pieces fit, and where you can dig in and adapt existing authorization / authentication flows to the needs of your application, is important, and forms the primary objective of this series.

The OAuth Owner Resource Flow Authentication Model

One of the commonly used patterns for authentication in a web application is the OAuth Resource Owner Flow model. In fact, this is the model used in the Web Api Template project in Visual Studio. We are going to implement authentication using the Resource Owner Flow from "almost scratch" in our OWIN-based Web Api application.

The Owner Resource Flow posits four principal "actors" in an authentication scenario:

  • The Resource Owner - For example, a user, or perhaps another application.
  • The Client - Generally a client application being used by the resource owner to access the protected resource. In our case, the Client might be our Web Api Client application.
  • The Authorization Server - A server which accepts the Resource Owners credentials (generally a combination of some form of credentials and a password, such as a User Name/Password combination) and returns an encoded or encrypted Access Token.
  • The Resource Server - The server on which the resource is located, and which protects the resource from unauthorized access unless valid authentication/authorization credentials are supplied with the request.
Overview of the Owner Resource Authentication Flow:

oath-resource-owner-flow

In the above, the Resource Owner presents a set of credentials to the Client. The Client then submits the credentials to the Authorization Server, and if the credentials can be properly validated by the Authorization Server, an encoded and/or encrypted Access Token is returned to the Client.

The Client then uses the Access Token to make requests to the Resource Server. The Resource Server has been configured to accept Access Tokens which originate at the Authorization Server, and to decode/decrypt those tokens to confirm the identity and authorization claims (if provided) of the Resource Owner.

All of this is predicated on the Resource Owner having been properly registered with the Authorization Server.

It should be noted there that the OAuth specification requires that any transaction involving transmission of password/credentials MUST be conducted using SSL/TSL (HTTPS).

Our implementation, and that of the VS Web Api project template, puts a slight twist on this, by embedding the Authentication Server within the Resource Server:

The Embedded Authentication Server Variant of the Owner Resource Flow:

oath-embedded-resource-owner-flow

The Basics - OWIN, Katana, and Authentication

We can put together a very stripped down example to demonstrate how the pieces fit together, before we clutter things up with higher-level components and any additional database concerns.

To get started, you can pull down the source for the Self-hosted web api we built in the previous post. We're going to pick up where we left off with that project, and add a basic authentication component.

Recall that we had assembled a fairly minimal Owin-Based Web Api, consisting of an OWIN Startup class, a simple Company model class, and a CompaniesController. The application itself is a console-based application, with a standard entry point in the Main() method of the Program class.

In that project, we had decided that since we were self-hosting the application, we would keep our data store in-process and use a local file-based data store. We opted to use SQL Server Compact Edition since it would readily work with Entity Framework and Code-First database generation. Therefore, we also added an ApplicationDbContext.

We can review our existing project components before we make any changes.

Starting Point - The Self-Hosted Web Api Project

First, we have our OWIN Startup class:

The OWIN Startup Class from the Minimal Self-Hosted Web Api Project:
// Add the following usings:
using Owin;
using System.Web.Http;
 
namespace MinimalOwinWebApiSelfHost
{
    public class Startup
    {
        // This method is required by Katana:
        public void Configuration(IAppBuilder app)
        {
            var webApiConfiguration = ConfigureWebApi();
 
            // Use the extension method provided by the WebApi.Owin library:
            app.UseWebApi(webApiConfiguration);
        }
 
 
        private HttpConfiguration ConfigureWebApi()
        {
            var config = new HttpConfiguration();
            config.Routes.MapHttpRoute(
                "DefaultApi",
                "api/{controller}/{id}",
                new { id = RouteParameter.Optional });
            return config;
        }
    }
}

 

Then, we had a simple Company model, suitably located in the Models folder in our project:

The Original Company Model Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add using:
using System.ComponentModel.DataAnnotations;
 
namespace MinimalOwinWebApiSelfHost.Models
{
    public class Company
    {
        // Add Key Attribute:
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

 

 

And our original CompaniesController class, again suitably located in the Controllers folder within our project::

The Original Companies Controller:
public class CompaniesController : ApiController
{
    ApplicationDbContext _Db = new ApplicationDbContext();
 
 
    public IEnumerable<Company> Get()
    {
        return _Db.Companies;
    }
 
 
    public async Task<Company> Get(int id)
    {
        var company = 
                await _Db.Companies.FirstOrDefaultAsync(c => c.Id == id);
        if (company == null)
        {
            throw new HttpResponseException(
                System.Net.HttpStatusCode.NotFound);
        }
        return company;
    }
 
 
    public async Task<IHttpActionResult> Post(Company company)
    {
        if (company == null)
        {
            return BadRequest("Argument Null");
        }
        var companyExists = 
                await _Db.Companies.AnyAsync(c => c.Id == company.Id);
 
        if (companyExists)
        {
            return BadRequest("Exists");
        }
 
        _Db.Companies.Add(company);
        await _Db.SaveChangesAsync();
        return Ok();
    }
 
 
    public async Task<IHttpActionResult> Put(Company company)
    {
        if (company == null)
        {
            return BadRequest("Argument Null");
        }
        var existing = 
                await _Db.Companies.FirstOrDefaultAsync(c => c.Id == company.Id);
 
        if (existing == null)
        {
            return NotFound();
        }
 
        existing.Name = company.Name;
        await _Db.SaveChangesAsync();
        return Ok();
    }
 
 
    public async Task<IHttpActionResult> Delete(int id)
    {
        var company = 
                await _Db.Companies.FirstOrDefaultAsync(c => c.Id == id);
        if (company == null)
        {
            return NotFound();
        }
        _Db.Companies.Remove(company);
        await _Db.SaveChangesAsync();
        return Ok();
    }
}

 

Also in the Models folder is our ApplicationDbContext.cs file, which actually contains the ApplicationDbContext itself, as well as a DBInitializer. For the moment, this derives from DropDatabaseCreateAlways, so that the database is blown away and re-seeded each time the application runs.

The Original ApplicationDbContext and DbInitializer:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add using:
using System.Data.Entity;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
 
namespace MinimalOwinWebApiSelfHost.Models
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext()
            : base("MyDatabase")
        {
 
        }
 
        static ApplicationDbContext()
        {
            Database.SetInitializer(new ApplicationDbInitializer());
        }
 
        public IDbSet<Company> Companies { get; set; }
    }
 
 
    public class ApplicationDbInitializer 
        : DropCreateDatabaseAlways<ApplicationDbContext>
    {
        protected override void Seed(ApplicationDbContext context)
        {
            context.Companies.Add(new Company { Name = "Microsoft" });
            context.Companies.Add(new Company { Name = "Apple" });
            context.Companies.Add(new Company { Name = "Google" });
            context.SaveChanges();
        }
    }
}

 

I actually changed the code for the original ApplicationDbContext since the previous post. I have added a static constructor which sets the Database Initializer when the context is instantiated. This will call the initializer the first time we hit the database.

This is a much cleaner solution than previously, where we were doing the database initialization in the Main() method of our Program class:

The Original Program.cs File (slightly modified):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add reference to:
using Microsoft.Owin.Hosting;
using System.Data.Entity;
using MinimalOwinWebApiSelfHost.Models;
 
namespace MinimalOwinWebApiSelfHost
{
    class Program
    {
        static void Main(string[] args)
        {
            // Specify the URI to use for the local host:
            string baseUri = "http://localhost:8080";
 
            Console.WriteLine("Starting web Server...");
            WebApp.Start<Startup>(baseUri);
            Console.WriteLine("Server running at {0} - press Enter to quit. ", baseUri);
            Console.ReadLine();
        }
    }
}

 

Now that we know where we left off, let's see about implementing a very basic example of the OAuth Resource Owner Flow model for authentication.

The Microsoft.AspNet.Identity.Owin Nuget Package includes everything we need to implement a basic example of the Resource Owner Flow, even though we won't be dealing with Identity directly just yet.

Pull the Microsoft.AspNet.Identity.Owin package into our project:

Add Microsoft ASP.NET Identity Owin Nuget Package:
PM> Install-Package Microsoft.AspNet.Identity.Owin -Pre

 

Now we are ready to get started…

Adding The Embedded Authorization Server

Key to the Resource Owner Flow is the Authorization Server. In our case, the Authorization Server will actually be contained within our Web Api application, but will perform the same function as it would if it were hosted separately.

The Microsoft.Owin.Security.OAuth library defines a default implementation of IOAuthAuthorizationServerProvider, OAuthAuthorizationServerProvider which allows us to derive a custom implementation for our application. You should recognize this if you have used the Visual Studio Web Api project templates before. Add a new folder to the project, OAuthServerProvider, and then add a class ass follows:

Add the ApplicationOAuthServerProvider Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add Usings:
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using System.Security.Claims;
using MinimalOwinWebApiSelfHost.Models;
 
namespace MinimalOwinWebApiSelfHost.OAuthServerProvider
{
    public class ApplicationOAuthServerProvider 
        : OAuthAuthorizationServerProvider
    {
        public override async Task ValidateClientAuthentication(
            OAuthValidateClientAuthenticationContext context)
        {
            // This call is required...
            // but we're not using client authentication, so validate and move on...
            await Task.FromResult(context.Validated());
        }
 
 
        public override async Task GrantResourceOwnerCredentials(
            OAuthGrantResourceOwnerCredentialsContext context)
        {
            // DEMO ONLY: Pretend we are doing some sort of REAL checking here:
            if (context.Password != "password")
            {
                context.SetError(
                    "invalid_grant", "The user name or password is incorrect.");
                context.Rejected();
                return;
            }
 
            // Create or retrieve a ClaimsIdentity to represent the 
            // Authenticated user:
            ClaimsIdentity identity = 
                new ClaimsIdentity(context.Options.AuthenticationType);
            identity.AddClaim(new Claim("user_name", context.UserName));
 
            // Identity info will ultimately be encoded into an Access Token
            // as a result of this call:
            context.Validated(identity);
        }
    }
}

 

You can see  we are overriding two of the methods available on OAuthAuthorizationServerProvider. The First, ValidateClientAuthentication(), is necessary even though in our case we are not validating the Client application (although we COULD, if we wanted to). We are simply calling Validated() on the ClientValidationContext and moving on. In a more complex scenario, or one for which stronger security was required, we might authenticate the client as well as the resource owner.

Where the meat and potatoes of our authentication process occurs is in the GrantResourceOwnerCredentials() method. For this part of our example, we're keeping this simple. We have hacked an authentication process which basically compares the password passed in with the hard-coded string value "password." IF this check fails, an error is set, and authentication fails.

In reality, of course, we would (and WILL, shortly) implement a more complex check of the user's credentials. For now though, this will do, without distracting us from the overall structure of things.

If the credentials check succeeds, an instance of ClaimsIdentity is created to represent the user data, including any Claims the user should have. For now, all we are doing is adding the user's name as the single claim, and then calling Validated() on the GrantResourceOwnerCredentials context.

The call to Validated() ultimately results in the OWIN middleware encoding the ClaimsIdentity data into an Access Token. How this happens, in the context of the Microsoft.Owin implementation, is complex and beyond the scope of this article. If you want to dig deeper on this, grab a copy of Telerik's fine tool Just Decompile. Suffice it to say that the ClaimsIdentity information is encrypted with a private key (generally, but not always the Machine Key of the machine on which the server is running). Once so encrypted, the access token is then added to the body of the outgoing HTTP response.

Configuring OWIN Authentication and Adding to the Middleware Pipeline

Now that we have our actual Authorization Server in place, let's configure our OWIN Startup class to authenticate incoming requests.

We will add a new method, ConfigureAuth() to our Startup class. Check to make sure you have added the following usings and code to Startup:

Add a ConfigureAuth() Method to the OWIN Startup Class:
using System;
 
// Add the following usings:
using Owin;
using System.Web.Http;
using MinimalOwinWebApiSelfHost.Models;
using MinimalOwinWebApiSelfHost.OAuthServerProvider;
using Microsoft.Owin.Security.OAuth;
using Microsoft.Owin;
 
namespace MinimalOwinWebApiSelfHost
{
    public class Startup
    {
        // This method is required by Katana:
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            var webApiConfiguration = ConfigureWebApi();
            app.UseWebApi(webApiConfiguration);
        }
 
 
        private void ConfigureAuth(IAppBuilder app)
        {
            var OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/Token"),
                Provider = new ApplicationOAuthServerProvider(),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
 
                // Only do this for demo!!
                AllowInsecureHttp = true
            };
            app.UseOAuthAuthorizationServer(OAuthOptions);
            app.UseOAuthBearerAuthentication(
                    new OAuthBearerAuthenticationOptions());
        }
 
 
        private HttpConfiguration ConfigureWebApi()
        {
            var config = new HttpConfiguration();
            config.Routes.MapHttpRoute(
                "DefaultApi",
                "api/{controller}/{id}",
                new { id = RouteParameter.Optional });
            return config;
        }
    }
}

 

There's a lot going on in the ConfigureAuth() method above.

First, we initialize an instance of OAuthAuthorizationServerOptions. As part of the initialization, we see that we set the token endpoint, as well as assign a new instance of our ApplicationOAuthAuthenticationServerProvider class to the Provider property of the options object.

We set an expiry for any tokens issues, and then we explicitly allow the Authorization Server to allow insecure HTTP connections. A note on this last - this is strictly for demo purposes. In the wild, you would definitely want to connect to the authorization server using a secure SSL/TLS protocol (HTTPS), since you are transporting user credentials in the clear.

Once our authorization server options are configured, we see the standard extension methods commonly used to add middleware to IAppBuilder. We pass our server options in with UseAuthorizationServer(), and then we indicate that we want to return Bearer Tokens with UseOAuthBearerAuthentication(). In this case, we are passing the default implementation for OAuthBearerAuthenticationOptions, although we could derive from that and customize if we needed to.

The server is added to the options object, which specifies other configuration items, and which is then passed into the middleware pipeline.

Authenticating the Client: Retrieve an Access Token from the Authorization Server

Again, from the previous post, we had put together a crude but effective API client application to exercise our API.

For this post, we are going to basically re-write the client application.

First, we will add a new Class, the apiClient class. This class will be responsible for submitting our credentials to our Web Api and obtaining a Dictionary<string, string> containing the de-serialized response body, which includes the access token, and additional information about the authentication process:

The ApiClient Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add Usings:
using System.Net.Http;
 
// Add for Identity/Token Deserialization:
using Newtonsoft.Json;
 
namespace MinimalOwinWebApiClient
{
    public class apiClientProvider
    {
        string _hostUri;
        public string AccessToken { get; private set; }
 
        public apiClientProvider(string hostUri)
        {
            _hostUri = hostUri;
        }
 
 
        public async Task<Dictionary<string, string>> GetTokenDictionary(
            string userName, string password)
        {
            HttpResponseMessage response;
            var pairs = new List<KeyValuePair<string, string>>
                {
                    new KeyValuePair<string, string>( "grant_type", "password" ), 
                    new KeyValuePair<string, string>( "username", userName ), 
                    new KeyValuePair<string, string> ( "password", password )
                };
            var content = new FormUrlEncodedContent(pairs);
 
            using (var client = new HttpClient())
            {
                var tokenEndpoint = new Uri(new Uri(_hostUri), "Token");
                response =  await client.PostAsync(tokenEndpoint, content);
            }
 
            var responseContent = await response.Content.ReadAsStringAsync();
            if (!response.IsSuccessStatusCode)
            {
                throw new Exception(string.Format("Error: {0}", responseContent));
            }
 
            return GetTokenDictionary(responseContent);
        }
 
 
        private Dictionary<string, string> GetTokenDictionary(
            string responseContent)
        {
            Dictionary<string, string> tokenDictionary =
                JsonConvert.DeserializeObject<Dictionary<string, string>>(
                responseContent);
            return tokenDictionary;
        }
    }
}

 

With that in place, we can re-implement the client Program class like so:

The Client Program Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add Usings:
using System.Net.Http;
 
namespace MinimalOwinWebApiClient
{
    class Program
    {
        static void Main(string[] args)
        {
            // Wait for the async stuff to run...
            Run().Wait();
 
            // Then Write Done...
            Console.WriteLine("");
            Console.WriteLine("Done! Press the Enter key to Exit...");
            Console.ReadLine();
            return;
        }
 
 
        static async Task Run()
        {
            // Create an http client provider:
            string hostUriString = "http://localhost:8080";
            var provider = new apiClientProvider(hostUriString);
            string _accessToken;
            Dictionary<string, string> _tokenDictionary;
 
            try
            {
                // Pass in the credentials and retrieve a token dictionary:
                _tokenDictionary = await provider.GetTokenDictionary(
                        "john@example.com", "password");
                _accessToken = _tokenDictionary["access_token"];
            }
            catch (AggregateException ex)
            {
                // If it's an aggregate exception, an async error occurred:
                Console.WriteLine(ex.InnerExceptions[0].Message);
                Console.WriteLine("Press the Enter key to Exit...");
                Console.ReadLine();
                return;
            }
            catch (Exception ex)
            {
                // Something else happened:
                Console.WriteLine(ex.Message);
                Console.WriteLine("Press the Enter key to Exit...");
                Console.ReadLine();
                return;
            }
 
            // Write the contents of the dictionary:
            foreach(var kvp in _tokenDictionary)
            {
                Console.WriteLine("{0}: {1}", kvp.Key, kvp.Value);
                Console.WriteLine("");
            }
        }
    }
}

 

Up to this point, we've ditched all the code that makes requests to the CompaniesController in our API, and we're only looking at the code which authenticates us and retrieves the access token.

Note, we have included some very rudimentary exception handling here. In a real application we would probably want a little more info, and we would need to incorporate a more robust mechanism for handling HTTP errors and other things that might go wrong.

If we run our Web Api application, and then run our client application, we should see the following output from our Client application:

Client Application Output after Authentication:

console-output-client-application-authentication 

And we see that we have successfully retrieved an access token from our extra-simple auth server. But, what if we pass invalid credentials?

Change the password we are passing in from "password" to something else, say, "assword" (but mom, all I did was take the letter "p" out??!!):

Client Application after Invalid Authentication:

console-output-client-application-invalid-authentication

Appropriately, we get back an error indicating we have provided an invalid grant.

Now let's implement the rest of our client, and try some calls into our API itself.

Implementing the API Client with Authenticated API Calls

Now, we'll add an updated version of the CompanyClient class. In this case, we have made everything async. Also, we have updated the class itself, and all of the methods, to work with the the new authentication requirement we have introduced in our API:

The Heavily Modified CompanyClient Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add Usings:
using System.Net.Http;
using System.Net;
using System.Net.Http.Headers;
 
// Add for Identity/Token Deserialization:
using Newtonsoft.Json;
 
 
namespace MinimalOwinWebApiClient
{
    public class CompanyClient
    {
        string _accessToken;
        Uri _baseRequestUri;
        public CompanyClient(Uri baseUri, string accessToken)
        {
            _accessToken = accessToken;
            _baseRequestUri = new Uri(baseUri, "api/companies/");
        }
 
 
        // Handy helper method to set the access token for each request:
        void SetClientAuthentication(HttpClient client)
        {
            client.DefaultRequestHeaders.Authorization 
                = new AuthenticationHeaderValue("Bearer", _accessToken); 
        }
 
 
        public async Task<IEnumerable<Company>> GetCompaniesAsync()
        {
            HttpResponseMessage response;
            using(var client = new HttpClient())
            {
                SetClientAuthentication(client);
                response = await client.GetAsync(_baseRequestUri);
            }
            return await response.Content.ReadAsAsync<IEnumerable<Company>>();
        }
 
 
        public async Task<Company> GetCompanyAsync(int id)
        {
            HttpResponseMessage response;
            using (var client = new HttpClient())
            {
                SetClientAuthentication(client);
 
                // Combine base address URI and ID to new URI
                // that looks like http://hosturl/api/companies/id
                response = await client.GetAsync(
                    new Uri(_baseRequestUri, id.ToString()));
            }
            var result = await response.Content.ReadAsAsync<Company>();
            return result;
        }
 
 
        public async Task<HttpStatusCode> AddCompanyAsync(Company company)
        {
            HttpResponseMessage response;
            using(var client = new HttpClient())
            {
                SetClientAuthentication(client);
                response = await client.PostAsJsonAsync(
                    _baseRequestUri, company);
            }
            return response.StatusCode;
        }
 
 
        public async Task<HttpStatusCode> UpdateCompanyAsync(Company company)
        {
            HttpResponseMessage response;
            using (var client = new HttpClient())
            {
                SetClientAuthentication(client);
                response = await client.PutAsJsonAsync(
                    _baseRequestUri, company);
            }
            return response.StatusCode;
        }
 
 
        public async Task<HttpStatusCode> DeleteCompanyAsync(int id)
        {
            HttpResponseMessage response;
            using (var client = new HttpClient())
            {
                SetClientAuthentication(client);
 
                // Combine base address URI and ID to new URI
                // that looks like http://hosturl/api/companies/id
                response = await client.DeleteAsync(
                    new Uri(_baseRequestUri, id.ToString()));
            }
            return response.StatusCode;
        }
    }
}

 

Now, we can update our Program class to call into CompanyClient to work with our API and output the results to the console. Basically, we'll expand the Run() method, and exercise each of the methods we defined on CompaniesController asynchronously. We also added a pair of convenience methods for writing to the console, WriteCompaniesList() and WriteStatusCodeResult() :

Update Program Class to Consume API and Write to Console:
static async Task Run()
{
    // Create an http client provider:
    string hostUriString = "http://localhost:8080";
    var provider = new apiClientProvider(hostUriString);
    string _accessToken;
    Dictionary<string, string> _tokenDictionary;
 
    try
    {
        // Pass in the credentials and retrieve a token dictionary:
        _tokenDictionary = 
            await provider.GetTokenDictionary("john@example.com", "password");
        _accessToken = _tokenDictionary["access_token"];
 
        // Write the contents of the dictionary:
        foreach (var kvp in _tokenDictionary)
        {
            Console.WriteLine("{0}: {1}", kvp.Key, kvp.Value);
            Console.WriteLine("");
        }
 
        // Create a company client instance:
        var baseUri = new Uri(hostUriString);
        var companyClient = new CompanyClient(baseUri, _accessToken);
 
        // Read initial companies:
        Console.WriteLine("Read all the companies...");
        var companies = await companyClient.GetCompaniesAsync();
        WriteCompaniesList(companies);
 
        int nextId = (from c in companies select c.Id).Max() + 1;
 
        Console.WriteLine("Add a new company...");
        var result = await companyClient.AddCompanyAsync(
            new Company { Name = string.Format("New Company #{0}", nextId) });
        WriteStatusCodeResult(result);
 
        Console.WriteLine("Updated List after Add:");
        companies = await companyClient.GetCompaniesAsync();
        WriteCompaniesList(companies);
 
        Console.WriteLine("Update a company...");
        var updateMe = await companyClient.GetCompanyAsync(nextId);
        updateMe.Name = string.Format("Updated company #{0}", updateMe.Id);
        result = await companyClient.UpdateCompanyAsync(updateMe);
        WriteStatusCodeResult(result);
 
        Console.WriteLine("Updated List after Update:");
        companies = await companyClient.GetCompaniesAsync();
        WriteCompaniesList(companies);
 
        Console.WriteLine("Delete a company...");
        result = await companyClient.DeleteCompanyAsync(nextId - 1);
        WriteStatusCodeResult(result);
 
        Console.WriteLine("Updated List after Delete:");
        companies = await companyClient.GetCompaniesAsync();
        WriteCompaniesList(companies);
    }
    catch (AggregateException ex)
    {
        // If it's an aggregate exception, an async error occurred:
        Console.WriteLine(ex.InnerExceptions[0].Message);
        Console.WriteLine("Press the Enter key to Exit...");
        Console.ReadLine();
        return;
    }
    catch (Exception ex)
    {
        // Something else happened:
        Console.WriteLine(ex.Message);
        Console.WriteLine("Press the Enter key to Exit...");
        Console.ReadLine();
        return;
    }
}
 
 
static void WriteCompaniesList(IEnumerable<Company> companies)
{
    foreach (var company in companies)
    {
        Console.WriteLine("Id: {0} Name: {1}", company.Id, company.Name);
    }
    Console.WriteLine("");
}
 
static void WriteStatusCodeResult(System.Net.HttpStatusCode statusCode)
{
    if (statusCode == System.Net.HttpStatusCode.OK)
    {
        Console.WriteLine("Opreation Succeeded - status code {0}", statusCode);
    }
    else
    {
        Console.WriteLine("Opreation Failed - status code {0}", statusCode);
    }
    Console.WriteLine("");
}

 

Now that we are able to properly authenticate requests to our Web Api, we should be protected against unauthorized access, right?

Not so fast.

Protecting Resources With [Authorize] Attribute

If we fire up our Web Api Application now, open a browser, and type the URL routed to the GetCompanies() method on the CompaniesController, we find that we can still access the resource, even though the requests from the browser contains no authentication token:

Accessing the Companies Resource from the Browser without Authentication:

access-unprotected-resource-from-browser

This is because we haven't specified that the resources represented by CompaniesController should be protected. We can fix that easily, by decorating the CompaniesController class itself with an [Authorize] attribute:

Decorate CompaniesController with an [Authorize] Attribute:
[Authorize]
public class CompaniesController : ApiController
{
    // ... Code for Companies Controller ...
}

 

If we re-run the Web Api application now, and refresh our browser, we find:

Accessing the Protected Companies Resource from the Browser without Authentication:

access-protected-resource-from-browser

Since the browser request had no access token in the request body, the request for the protected resource was denied.

Accessing Protected Resources with Authenticated Client Requests

Now, we should be able to run our API Client application (don't forget to re-set the password to "password!"). If we run our client application now, we should see console output resembling the following:

Console Output from Authenticated Request for Protected Resource:

console-output-client-application-with-authenticated-api-calls

With that, we have implemented a very basic example of authenticating a user with our embedded authorization server, retrieved an access token from our client application, and successfully requested access to protected resources on the resource server.

Adding Roles as Claims

A deep look at claims-based authorization is beyond the scope of this article. However, we can use the [Authorize] attribute to ensure that only users with a specific role claim can access a protected resource:

Change the [Authorize] attribute on the CompanyController class to the following:

Add a specific Role to the [Authorize] Attribute on Company Controller:
[Authorize(Roles="Admin")]
public class CompaniesController : ApiController
{
    // ... Code for Companies Controller ...
}

 

If we run our Web Api application now, and then run our Api Client application, we find we have a problem:

Running the Api Client when Role Authorization is Required:

api-error-unauthorized-with-role-required

Given we have added the Role restriction for access to the CompaniesController resource, this is what we expect to see. Now let's see about authorizing access based on Role membership in our Web Api.

Add a Role Claim to Resource Owner Identity

At the simplest level, we can add a claim to the access token granted to the resource owner in the call to GrantResourceOwnerCredentials():

Add a Role Claim to the authenticated User in GrantResourceOwnerCredentials():
public override async Task GrantResourceOwnerCredentials(
    OAuthGrantResourceOwnerCredentialsContext context)
{
    // DEMO ONLY: Pretend we are doing some sort of REAL checking here:
    if (context.Password != "password")
    {
        context.SetError(
            "invalid_grant", "The user name or password is incorrect.");
        context.Rejected();
        return;
    }
 
    // Create or retrieve a ClaimsIdentity to represent the 
    // Authenticated user:
    ClaimsIdentity identity = 
        new ClaimsIdentity(context.Options.AuthenticationType);
    identity.AddClaim(new Claim("user_name", context.UserName));
 
    // Add a Role Claim:
    identity.AddClaim(new Claim(ClaimTypes.Role, "Admin"));
   
    // Identity info will ultimatly be encoded into an Access Token
    // as a result of this call:
    context.Validated(identity);
}

With that simple change, we have now added a claim to the identity of the authenticated user. The claims will be encoded/encrypted as part of the access token. When the token is received by the resource server (in this case, our application), the decoded token will provide the identity of the authenticated user, as well as any additional claims, including the fact that the user is a member of the "Admin" role.

If we run both applications now, the console output from our Api Client application is what we would expect:

Console Output from Client with Authenticated User with Proper Admin Role Claim:

api-successful-access-with-role-required

We have once again successfully accessed a protected resource. Access to the CompaniesController is now restricted to authenticated users who also present a claim indicating they are a member of the Admin role.

What Next?

So far, we've seen in a very basic way how the Resource Owner Flow is implemented in the context of the OWIN/Katana pipeline. We have not yet examined where we might store our user information, how we get it there, or how our authorization framework might access that data.

In the next post, we'll look at persisting authorization information, and how we access it.

NEXT: ASP.NET Web Api: OWIN/Katana Authentication/Authorization Part II: Models and Persistence

Additional Resources and Items of Interest

Some very helpful articles I have referred to in learning this stuff:

 

Posted on January 19 2015 12:45 PM by jatten     

Comments (3)

About the author

My name is John Atten, and my "handle" on many of my online accounts is xivSolutions. I am Fascinated by all things technology and software development. I work mostly with C#, JavaScript/Node, and databases of many flavors. Actively learning always. I dig web development. I am always looking for new information, and value your feedback (especially where I got something wrong!). You can email me at:

johnatten at typecastexception dot com

Web Hosting by