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

Posted on January 25 2015 09:23 AM by jatten in ASP.Net, ASP.NET MVC, C#   ||   Comments (0)

authorized-personnel-only-320In the previous post in this series we learned how the most basic authentication and authorization elements fit together in an OWIN-based Web Api application. We have seen how to authenticate a user using an Authentication Server embedded within our application, and how to add an elementary claim to use with the [Authorize] attribute.

To this point, we have been avoiding using the ready-built Identity framework, and instead we have been focusing on understanding how these pieces interrelate. We will continue this approach (for now) here, by adding some concrete authorization models to our application, and a persistence layer to store important user data.

Image by clement127  |  Some Rights Reserved

Once again, we will be doing most of this "from scratch," in a pretty minimal fashion. I want to explore the relationships between project components without too many distractions. So we're not attempting to design the optimal auth system here or demonstrate the latest best practices. But hopefully we will come away with a better understanding of how a fully developed authentication/authorization system such as Identity works in the context of our application. Understanding THAT gives empowers us to utilize tools like Identity more effectively.

From the Ground Up

In this series of posts we started with concepts, and are building slowly build from there.

  • Part I (last 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 (this post) - 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).

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:

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. This is where we left the code in the last post.

Adding Auth Models to the Minimal Web Api

We'll be starting from where we left off in the last post. Recall that We had set up a basic embedded authorization server in our application which would process HTTP POST requests made by a client to the token endpoint, validate the user credentials/password received, and return an access token. From there, the client could submit the access token with subsequent requests to authenticate, and access whichever resources are available for the given identity and/or role.

If we review our existing code for the ApplicationOAuthServerProvider, we see in the GrantOwnerResourceCredentials() method that we are performing a mock credentials check. In order to keep things simple, we just checked to see if the password submitted matched the string literal "password" and moved on:

The Existing GrantOwnerResourceCredentials Method:
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.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);
}

 

In reality, we would most likely check to see if there was a user in our backing store which matched whatever credentials were submitted, and then also check to see if the password submitted was valid. But not by checking against a plain text representation from our backing store!

In order to flesh out this method, we need to model our authorization objects, and we need to persist some user data in our database.

First, let's add some basic models. Add a new code file to the Models folder in the project, and then add the following code:

The AuthModels.cs Code File:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add usings:
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
using System.Security.Claims;
 
namespace MinimalOwinWebApiSelfHost.Models
{
    public class MyUser
    {
        public MyUser()
        {
            Id = Guid.NewGuid().ToString();
            Claims = new List<MyUserClaim>();
        }
 
        [Key]
        public string Id { get; set; }
        public string Email { get; set; }
        public string PasswordHash { get; set; }
        public ICollection<MyUserClaim> Claims { get; set; }
    }
 
 
    public class MyUserClaim
    {
        public MyUserClaim()
        {
            Id = Guid.NewGuid().ToString();
        }
        [Key]
        public string Id { get; set; }
        public string UserId { get; set; }
        public string ClaimType { get; set; }
        public string ClaimValue { get; set; }
    }
 
 
    public class MyPasswordHasher
    {
        public string CreateHash(string password)
        {
            // FOR DEMO ONLY! Use a standard method or 
            // crypto library to do this for real:
            char[] chars = password.ToArray();
            char[] hash = chars.Reverse().ToArray();
            return new string(hash);
        }
    }
}

 

Above, we see a few basic models. We expect to have a user representation, and we do, in the form of the MyUser class. While you may have been expecting to see a MyRole class, we have instead opted to carry on with the claims implementation we were using in our original project. Therefore, we have added a MyUserClaim class instead. We'll discuss this further shortly.

Finally, we have that odd-looking MyPasswordHasher class. As you may have guessed from the comment in the code, we are really only going to mock a proper hashing mechanism here. As before, we're going to keep things simple for our example. In reality, one would apply a proven crypto library to this task, and proven, tried and true methods for properly hashing a password. Or, of course, use a library for such things, like Identity.

Adding The Models to the ApplicationDbContext

Now that we have our auth-related entity models, we can add them to the existing ApplicationDbContext so that they can be modeled in the database, and we can access the data they represent from the context.

Recall that we set this particular example application up to use a local, file-based database (SQL CE) however, everything we are doing here would work just fine with SQL Server as well.

Add the Auth-Related Models to the ApplicationDbContext:
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; }
}

 

Tying the Models Together - The User Store

For our simple model set, and to keep concept straightforward, we are going to implement a simple MyUserStore class, and add sufficient functionality to get our application working and no more.

Add the following class (I added this to the AuthModels.cs file, but you can add it in its own if you want):

The UserStore Class:
public class MyUserStore
{
    ApplicationDbContext _db;
    public MyUserStore(ApplicationDbContext context)
    {
        _db = context;
    }
 
 
    public async Task AddUserAsync(MyUser user, string password)
    {
        if (await UserExists(user))
        {
            throw new Exception(
                "A user with that Email address already exists");
        }
        var hasher = new MyPasswordHasher();
        user.PasswordHash = hasher.CreateHash(password).ToString();
        _db.Users.Add(user);
        await _db.SaveChangesAsync();
    }
 
 
    public async Task<MyUser> FindByEmailAsync(string email)
    {
        var user = _db.Users
            .Include(c => c.Claims)
            .FirstOrDefaultAsync(u => u.Email == email);
        return await _db.Users
            .FirstOrDefaultAsync(u => u.Email == email);
    }
 
 
    public async Task<MyUser> FindByIdAsync(string userId)
    {
        return await _db.Users
            .FirstOrDefaultAsync(u => u.Id == userId);
    }
 
 
    public async Task<bool> UserExists(MyUser user)
    {
        return await _db.Users
            .AnyAsync(u => u.Id == user.Id || u.Email == user.Email);
    }
 
 
    public async Task AddClaimAsync(string UserId, MyUserClaim claim)
    {
        var user = await FindByIdAsync(UserId);
        if(user == null)
        {
            throw new Exception("User does not exist");
        }
        user.Claims.Add(claim);
        await _db.SaveChangesAsync();
    }
 
 
    public bool PasswordIsValid(MyUser user, string password)
    {
        var hasher = new MyPasswordHasher();
        var hash = hasher.CreateHash(password);
        return hash.Equals(user.PasswordHash);
    }
}

 

In the code above, we have assembled a few basic methods to deal with persisting and retrieving User information. Note in the AddUserAsync() method, we perform some minimal validation (make sure a user with the same email address does not already exist). Also, see that we use our super-secret, super-secure MyPasswordHasher to hash, salt, re-hash, etc. our user password, and then we persist the hashed value (NEVER the clear-text password). In other words, at no point are we saving the user-submitted clear-text password to disk, anywhere.

Similarly, we provide a simple PasswordIsValid() method which again uses the MyPasswordHasher class to compare the hash of the password submitted with that of a user record (which for now, would be submitted as an argument after being previously retrieved elsewhere in our code).

The MyUserStore class provides simplistic examples of how one might implement some of this. There is minimal validation and exception handling here. This class works well for our example, and to demonstrate the concepts we are dealing with, but is not likely how you would do this in a production application.

Initialize the Database with User Data

Now all we really need to do is update our ApplicationDbInitializer to seed the database with some initial user data. Recall, we had already set this up (in the same code file as the ApplicationDbContext) to seed our Company table with some starting data. Update the code as follows. You will also need to add System.Security.Claims to the using statements at the top of your code file:

Update ApplicationDbInitializer to Seed Application with Initial User Data:
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, 
            serId = 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");
    }
}

 

As we see above, we have taken advantage of the methods exposed on our new MyUserStore class to add two users, along with appropriate claims, to the database.

Also recall we are deriving our initializer from DropDatabaseCreateAlways so that the database will be re-created and re-seeded each time we run the application.

Find the User and Authenticate the Token Request

All that's left to do now is update our GrantResourceOwnerCredentials() method to avail itself of our new user entities and data to perform its function.

Validate and Authenticate a User in GrantResourceOwnerCredentials() Method:
public override async Task GrantResourceOwnerCredentials(
    OAuthGrantResourceOwnerCredentialsContext context)
{
    // Retrieve user from database:
    var store = new MyUserStore(new ApplicationDbContext());
    var user = await store.FindByEmailAsync(context.UserName);
 
    // Validate user/password:
    if(user == null || !store.PasswordIsValid(user, context.Password))
    {
        context.SetError(
            "invalid_grant", "The user name or password is incorrect.");
        context.Rejected();
        return;
    }
 
    var identity = new ClaimsIdentity(context.Options.AuthenticationType);
    foreach(var userClaim in user.Claims)
    {
        identity.AddClaim(new Claim(userClaim.ClaimType, userClaim.ClaimValue));
    }
     
    context.Validated(identity);
}

 

Here, we retrieve a user record from our store (if there is a record for the user credentials in the request), and then we create a new ClaimsIdentity for that user, much the same as before. This time, however, we also have a record of the various claims for this user, and we add those as well.

In this case, we really only have the user's name, and the role(s) our application recognizes for the user, but we could implement a more complex claims model if we needed. For now, we will stick with user name and roles, because the default authorization scheme, using the [Authorize] attribute, is pre-configured to work with user names and roles. We will look at customizing this in a later post.

The Api Client Application

We can leave our Api Client application pretty much as-is at the moment. If you don't have the client application set up, you can pull down the source for the project from the Github repo. Make sure to checkout the branch owin-auth (not master!).

Recall that we has set up our application to request a token from our Api, and then make some Api calls to the CompaniesController:

Abbreviated Client Code Showing the Token Request:
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", "JohnsPassword");
        _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);
 
        // ... a bunch of code calling to API and writing to console...
    }
    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;
    }
}

 

The only thing we have changed in the above code is the password we are passing in with the token request - we have changed it to match the password for the user record we created in our Seed() method.

Running the Application with an Authenticated User

If we run our Web Api application, and then run the client, everything should work swimmingly. The Web Api application spins up the same as it always has, and the client output should look familiar:

Console Output from Client Application:

client-with-authneticated-user

Everything looks the same as it did when we wrapped up the previous post, because we haven't changed anything the affects how the client application does its job. We've only changed the internals of our Web Api so that the embedded authorization server now knows how to retrieve user data from our database in order to authenticate a user, and perform a basic authorization check against the roles available to that user.

Let's see what happens when things go wrong.

Improper Authentication - Invalid Credentials

First, let's see what happens if we try to request a token with the wrong password. In the client application, change the password we are using in our token request to something other than "JohnsPassword":

Using Incorrect Password for Client Token Request:
// Pass in the credentials and retrieve a token dictionary:
_tokenDictionary = await provider.GetTokenDictionary(
    "john@example.com", "SomePassword");
_accessToken = _tokenDictionary["access_token"];

 

If we run the client again, we see all is not well:

Running the Client with Invalid Credentials:

client-with-invalid-password

In this case, were get back an "Invalid Grant" because the client could not properly authenticate with the credentials provided.

On the other hand, things look a little different is we request a token for a user which can be authenticated, but who is not authorized access to the resource requested.

Insufficient Authorization

Recall that in our Web Api application, we protected the CompaniesController resource using the [Authorize] attribute, and we restricted access to users in the role "Admin":

The CompaniesController is Protected Using [Authorize]:
[Authorize(Roles="Admin")]
public class CompaniesController : ApiController
{
    // ... blah blah Controller Methods etc...
    
}

 

Also recall that we seeded two users in our database. The user "jimi" does not have a claim for the "Admin" role, but instead claims the "User" role. Let's change the code in our client application to request an access token for "jimi" instead, and then see what happens.

Change Client Token Request for Alternate User:
// Pass in the credentials and retrieve a token dictionary:
_tokenDictionary = await provider.GetTokenDictionary(
    "jimi@example.com", "JimisPassword");
_accessToken = _tokenDictionary["access_token"];

 

Running the client application now produces a slightly different result:

Running the Client with Valid Credentials but Insufficient Authorization:

client-with-insufficient-authorization

Unlike previously, we did not receive an invalid grant error, because the user credentials were properly authenticated. However, the user does not possess the proper Role claim in our system to access the protected resource.

In reality, the default implementation of [Authorize] limits our ability to leverage claims to the fullest extent. [Authorize] recognizes claims for user names, and roles. What if we want more granular control over our application permissions?

We're not going to go into that in this post. However, keep this in mind, as leveraging Claims, and customizing authentication using claims instead of simple roles can become important for more complex application which require fine-grained control of permissions.

What Next?

In this post we created a "quick and dirty" implementation which performs some very basic authentication and authorization for our application.

In the real world, we would definitely tend to some critical details, such as proper crypto for hashing passwords. We would also probably want to beef up our design by applying some common patterns of abstraction. Notice, we have coded everything here directly to the implementation class. Also, we have rather tightly coupled our logical processing to our persistence model.

Lastly, we have put in place only the most rudimentary validation and exception handling.

We could go down a long road exploring how to better separate our persistence mechanism from our authentication logic, and more effectively handling exceptions and errors. However, those details are often application-specific, and/or require a long, long post.

Instead, we could now take everything we have learned, and pull in some ready-made components which already provide all of this, and more.

If the work we have done so far has been beginning to look a little familiar, that is no accident.

In the next post, we will implement our own authentication and authorization using the Identity 2.1 Framework.

Additional Resources and Items of Interest

Articles by others I have found invaluable:

 

Posted on January 25 2015 09:23 AM by jatten     

Comments (0)

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#   ||   Comments (2)

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.

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 (2)

ASP.NET Web Api 2.2: Create a Self-Hosted OWIN-Based Web Api from Scratch

Posted on January 11 2015 05:13 PM by jatten in ASP.NET MVC, ASP.Net, C#, CodeProject   ||   Comments (2)

Network-500Building up a lean, minimal Web Api application from scratch is a terrific way to become more familiar with how things work under the hood in a Web Api (or any other ASP.NET) project.

The ASP.NET team provides exceptional project templates that allow developers to get started easily building web applications. The templates are structured in a way which provides a basic, boilerplate functionality for getting up and running easily. The basic application infrastructure is all in place, and all the Nuget packages and framework references you might need are all there, ready to go.

Image by Ivan Emelianov  |  Some Rights Reserved

This is all great, but also creates a two-pronged problem, particularly for those still learning web development in general, and how to navigate the innards of ASP.NET MVC and Web Api Application development specifically.

First off, the generalized approach showcased in the VS project templates tends to include a good deal more "stuff" than any one application needs. In order to provide sufficient functionality out of the box to get devs up and running quickly, and to provide a starting point for a broad variety of basic application requirements, the templates in Visual Studio bring with them a good deal of infrastructure and libraries you don't need for your specific application.

Secondly, the templates knit together complete, ready-to-run applications in such a way that a whole lot appears to happen "by magic" behind the scenes, and it can be difficult to understand how these individual pieces fit together. This begins to matter when we want to customize our application, cut out unwanted components, or take a different architectural approach to building our application.

NOTE: In this post we will build out a simple Web Api example from scratch. The objective here is as much about understanding how ASP.NET components such as Web Api can plug into the OWIN/Katana environment, and how the various application components relate, as it is about simply "give me the codez." There are already plenty of examples showing how to cobble together a self-hosted web api application, "Hello World" examples, and such. In this post, we will seek to understand the "why" as much as the "how."

Understanding how these components fit together, and the notion of the middleware pipeline will become increasingly important as ASP.NET 5 ("vNext") moves closer and closer to release. While the implementation of the the middleware pipeline itself will change somewhat with the coming release, the concepts will apply even more strongly, and more globally to the ASP.NET ecosystem.

Source Code for Examples

The source code for the example projects used in this post can be found in my Github repo. There are two branches for the self-hosted Web Api Application, one with the basic API structure in place, and one after we add Entity Framework and a database to the equation.

Web Api and the OWIN Middleware Pipeline

As of ASP.NET 4.5.1, Web Api can be used as middleware in an OWIN/Katana environment. In a previous post we took a look at how the OWIN/Katana middleware pipeline can form the backbone, so to speak, of a modern ASP.NET web application.

The OWIN specification establishes a distinction between the host process, the web server, and a web application. IIS, in conjunction with ASP.NET, acts as both the host process and the server. The System.Web library, a heavy, all-things-to-all-people library, is tightly coupled to IIS. Web Applications with components which rely on System.Web, such as MVC (for the moment, until MVC 6 "vNext") and Web Forms are the likewise bound to IIS.

In the standard ASP.NET Web Api project template, Web Api is configured as part of the IIS/ASP.NET processing pipeline, as is MVC and most of the other ASP.NET project components (Identity 2.0 is a notable exception, in that Identity uses the OWIN pipeline by default in all of the project templates). However, beginning with ASP.NET 4.5.1, Web Api (and SignalR) can also be configured to run in an OWIN pipeline, relieved of reliance upon the infrastructure provided by IIS and the monolithic System.Web library.

In this post, we will configure Web Api as a middleware component in a lightweight OWIN-based application, shedding the dependency on the heavy System.Web library.

Plugging Application Components into the OWIN/Katana Pipeline

Recall from our previous post the simple graphic describing the interaction of middleware components in the Katana pipeline, and how the Katana implementation of the OWIN specification facilitates the interaction between the hosting environment, the server, and the application:

The Simplified OWIN Environment:

owin-middleware-chain

If we review how this works, we recall that we can plug middleware into the pipeline in a number of ways, but the most common mechanism is by providing an extension method for our middleware to act as a "hook" or point of entry. Middleware is commonly defined as a separate class, like so:

Simplified Middleware Component:
public class MiddlewareComponent
{
    AppFunc _next;
    public MiddlewareComponent(AppFunc next)
    {
        _next = next;
 
        // ...Other initialization processing...
    }
 
    public async Task Invoke(IDictionary<string, object> environment)
    {
    	// ...Inbound processing on environment or HTTP request...
 
    	// Invoke next middleware component:
        await _next.Invoke(environment);
 
        // ...outbound processing on environment or HTTP request...
    }
}

 

Then, in order to plug a component into the middleware pipeline in Katana, we commonly provide an extension method according to a the convention:

Extension Method to Plug Middleware into the Katana Pipeline:
public static class AppBuilderExtensions
{
    public static void UseMiddelwareComponent(this IAppBuilder app)
    {
        app.Use<MiddlewareComponent>();
    }
}

 

This allows us to plug MiddlewareComponent into the Katana pipeline during the call to Configuration() in our OWIN Startup class:

Plugging a Middleware into Katana Using the Extension Method:
public void Configuration(IAppBuilder app)
{
    app.UseMiddlewareComponent();
}

 

When we want to use ASP.NET Web Api as a component in an OWIN-based application, we can do something similar.

Plugging Web Api into an OWIN/Katana Application

When we want to use Web Api in an OWIN-based application instead of relying on System.Web, we can install the Microsoft.AspNet.WebApi.Owin Nuget package. This package provides a hook, similar to the above, which allows us to add Web Api to our Middleware pipeline. Once we do that, our diagram might look more like this:

OWIN/Katana Middleware Pipeline with Web Api Plugged In:

owin-middleware-chain w webapi

The Microsot.AspNet.WebApi.Owin package provides us with the UseWebApi() hook, which we will use to plug Web Api into a stripped-down, minimal application. First, we'll look at creating a simple self-hosted Web Api, and then we will see about using the Katana pipeline to use Web Api in an application hosted on IIS, but forgoing the heavy dependency on System.Web.

Creating a Self-Hosted OWIN-Based Web Api

We'll start by creating a bare-bones, self-hosted Web Api using a Console application as its base. First, create a new Console project in Visual Studio, then pull down the Microsoft.AspNet.WebApi.OwinSelfHost Nuget package:

Install Web Api 2.2 Self Host Nuget Package:
PM> Install-Package Microsoft.AspNet.WebApi.OwinSelfHost -Pre

 

The Microsoft.AspNet.WebApi.OwinSelfHost Nuget package installs a few new references into our project, among them Microsoft.Owin.Hosting and Microsoft.Owin.Host.HttpListener. Between these two libraries, our application can now act as its own host, and listen for HTTP requests over a port specified when the application starts up.

With that in place, add a new Class named Startup, and add the following code:

The Startup Class for a Katana-based Web Api:
// 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;
        }
    }
}

 

As we can see, all we are really doing is setting up our default routing configuration here, similar to what we see in the standard VS template project. However, instead of adding the routes specified to the routes collection in the ASP.NET pipeline, we are instead passing the HttpConfiguration as an argument to the app.UseWebApi() extension method.

Next, lets set up the familiar ASP.NET Web Api folder structure. Add a Models folder, and a Controllers folder. Then add a Company class to the Models folder:

Add a Company Class to the Models Folder:
public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
}

 

Next, add a CompaniesController Class to the Controllers folder:

Add a CompaniesController to the Controllers Folder:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add these usings:
using System.Web.Http;
using System.Net.Http;
using MinimalOwinWebApiSelfHost.Models;
 
namespace MinimalOwinWebApiSelfHost.Controllers
{
    public class CompaniesController : ApiController
    {
        // Mock a data store:
        private static List<Company> _Db = new List<Company>
            {
                new Company { Id = 1, Name = "Microsoft" },
                new Company { Id = 2, Name = "Google" },
                new Company { Id = 3, Name = "Apple" }
            };
 
 
        public IEnumerable<Company> Get()
        {
            return _Db;
        }
 
 
        public Company Get(int id)
        {
            var company = _Db.FirstOrDefault(c => c.Id == id);
            if(company == null)
            {
                throw new HttpResponseException(
                    System.Net.HttpStatusCode.NotFound);
            }
            return company;
        }
 
 
        public IHttpActionResult Post(Company company)
        {
            if(company == null)
            {
                return BadRequest("Argument Null");
            }
            var companyExists = _Db.Any(c => c.Id == company.Id);
 
            if(companyExists)
            {
                return BadRequest("Exists");
            }
 
            _Db.Add(company);
            return Ok();
        }
 
 
        public IHttpActionResult Put(Company company)
        {
            if (company == null)
            {
                return BadRequest("Argument Null");
            }
            var existing = _Db.FirstOrDefault(c => c.Id == company.Id);
 
            if (existing == null)
            {
                return NotFound();
            }
 
            existing.Name = company.Name;
            return Ok();
        }
 
 
        public IHttpActionResult Delete(int id)
        {
            var company = _Db.FirstOrDefault(c => c.Id == id);
            if (company == null)
            {
                return NotFound();
            }
            _Db.Remove(company);
            return Ok();
        }
    }
}

 

In the above code, for the moment, we are simply mocking out a data store using a List<Company>. Also, in a real controller we would probably implement async controller methods, but for now, this will do.

To complete the most basic functionality of our self-hosted Web Api application, all we need to do is set up the Main() method to start the server functionality provided by HttpListener. Add the following usings and code the the Program.cs file:

Start the Application in the Main() Method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add reference to:
using Microsoft.Owin.Hosting;
 
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();
        }
    }
}

 

Most of the structure above should look vaguely familiar, if you have worked with a Web Api or MVC project before.

Now all we need is a suitable client application to consume our self-hosted Web Api.

Create a Basic Web Api Client Application

We will create a simple Console application to use as a client in consuming our Web Api. Create a new Console application, and then add the Microsoft.AspNet.WebApi.Client library from Nuget:

Add the Web Api 2.2 Client Library from Nuget:
PM> Install-Package Microsoft.AspNet.WebApi.Client -Pre

 

Now, add a class named CompanyClient and add the following using statements and code:

Define the CompanyClient Class in the Web Api Client Application:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add Usings:
using System.Net.Http;
 
namespace MinimalOwinWebApiClient
{
    public class CompanyClient
    {
        string _hostUri;
        public CompanyClient(string hostUri)
        {
            _hostUri = hostUri;
        }
 
 
        public HttpClient CreateClient()
        {
            var client = new HttpClient();
            client.BaseAddress = new Uri(new Uri(_hostUri), "api/companies/");
            return client;
        }
 
 
        public IEnumerable<Company> GetCompanies()
        {
            HttpResponseMessage response;
            using (var client = CreateClient())
            {
                response = client.GetAsync(client.BaseAddress).Result;
            }
            var result = response.Content.ReadAsAsync<IEnumerable<Company>>().Result;
            return result;
        }
 
 
        public Company GetCompany(int id)
        {
            HttpResponseMessage response;
            using (var client = CreateClient())
            {
                response = client.GetAsync(
                	new Uri(client.BaseAddress, id.ToString())).Result;
            }
            var result = response.Content.ReadAsAsync<Company>().Result;
            return result;
        }
 
 
        public System.Net.HttpStatusCode AddCompany(Company company)
        {
            HttpResponseMessage response;
            using (var client = CreateClient())
            {
                response = client.PostAsJsonAsync(client.BaseAddress, company).Result;
            }
            return response.StatusCode;
        }
 
 
        public System.Net.HttpStatusCode UpdateCompany(Company company)
        {
            HttpResponseMessage response;
            using (var client = CreateClient())
            {
                response = client.PutAsJsonAsync(client.BaseAddress, company).Result;
            }
            return response.StatusCode;
        }
 
 
        public System.Net.HttpStatusCode DeleteCompany(int id)
        {
            HttpResponseMessage response;
            using (var client = CreateClient())
            {
                response = client.DeleteAsync(
                	new Uri(client.BaseAddress, id.ToString())).Result;
            }
            return response.StatusCode;
        }
    }
}

 

We've written (rather hastily, I might add) a crude but simple client class which will exercise the basic API methods we have defined on out Web Api application. We're working against a mock data set here, so we take some liberties with Id's and such in order to run and re-run the client application without running into key collisions.

We see in the above, we created a convenience/factory method to provide an instance of HttpClient as needed, pre-configured with a base Uri matching the route for the ClientController in our Web Api. From there, we simply define a local method corresponding to each API method, which we can use in our console application.

We can get this thing into running order by adding the following code to the Program.cs file of the client application:

The Program.cs File for the API Client Application:
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)
        {
            Console.WriteLine("Read all the companies...");
            var companyClient = new CompanyClient("http://localhost:8080");
            var companies = companyClient.GetCompanies();
            WriteCompaniesList(companies);
 
            int nextId  = (from c in companies select c.Id).Max() + 1;
 
            Console.WriteLine("Add a new company...");
            var result = companyClient.AddCompany(
            	new Company 
            	{ 
            		Id = nextId, 
            		Name = string.Format("New Company #{0}", nextId) 
        		});
            WriteStatusCodeResult(result);
 
            Console.WriteLine("Updated List after Add:");
            companies = companyClient.GetCompanies();
            WriteCompaniesList(companies);
 
            Console.WriteLine("Update a company...");
            var updateMe = companyClient.GetCompany(nextId);
            updateMe.Name = string.Format("Updated company #{0}", updateMe.Id);
            result = companyClient.UpdateCompany(updateMe);
            WriteStatusCodeResult(result);
 
            Console.WriteLine("Updated List after Update:");
            companies = companyClient.GetCompanies();
            WriteCompaniesList(companies);
 
            Console.WriteLine("Delete a company...");
            result = companyClient.DeleteCompany(nextId -1);
            WriteStatusCodeResult(result);
 
            Console.WriteLine("Updated List after Delete:");
            companies = companyClient.GetCompanies();
            WriteCompaniesList(companies);
 
            Console.Read();
        }
 
 
        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, if we run the Self-Hosted Web Api, we should see the following console output after it has started up:

Console Output from the Self-Hosted Web Api Startup:

console-output-web-api-startup

And then, when we run our client application, we should see the following:

Console Output from the Web Api Client Application:

console-output-client-startup

We see just about what we expect, given the code we have written. We query our Web Api for a lit of companies. We then add a new company, and refresh the list. Then we update the company we just added, review the list yet again. Finally, we remove the company just before the new company in the list, and review the list one last time.

Adding a Database and Entity Framework to the Self-Hosted Web Api

So far so good. However, a Web Api (even a small, self-hosted one) is of little use without some mechanism to persist and retreive data. We can add a database, and use Entity Framework in our self-hosted Web Api.

Since we are self-hosting, we may (depending upon the needs of our application) want to also use a local, in-process database as well (as opposed to a client/server solution) to keep our Web Api completely self-contained. Ordinarily I would go to SQLite for this, but to keep things simple we will use SQL CE. There is an Entity Framework provider for SQLite, however, it does not play too nicely with EF Code-First.

You can use SQLite with Entity Framework if you don't mind creating your database manually (or employing some work-arounds to get things working with code first), but for our purposes, SQL CE will do.

We don't HAVE to use a local database, of course. Depending upon your application, you may very well want to connect to SQLServer, or some other external database. If so, most of the following will work just as well if you pull down the standard Entity Framework package and work against SQL Server

To add a SQL Server Compact Edition database, we can simply go to Nuget again, and pull in the EntityFramework.SqlServerCompact Nuget package:

Add the Entity Framework SQL CE Nuget Package to the Web Api Application:
PM> Install-Package EntityFramework.SqlServerCompact

 

With that done, let's do a little housekeeping in order to pave the way for our new database.

Add an ApplicationDbContext and Initializer for Entity Framework

First, we need to add an a data context class. Also, we will want to use a database initializer we can call when the application runs to apply any changes. Also, for this particular case, we will set things up so that the database is recreated and re-seeded with data each time:

If we did not want to drop and re-create each time, we would derive from DropCreateDatabaseIfModelChanges instead of DropCreateDatabaseAlways

Add an ApplicationDbContext and Initializer Classes to the Models Folder:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add using:
using System.Data.Entity;
 
namespace MinimalOwinWebApiSelfHost.Models
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext() : base("MyDatabase")
        {
        }
        public IDbSet<Company> Companies { get; set; }
    }
 
 
    public class ApplicationDbInitializer : DropCreateDatabaseAlways<ApplicationDbContext>
    {
        protected override void Seed(ApplicationDbContext context)
        {
            base.Seed(context);
            context.Companies.Add(new Company { Name = "Microsoft" });
            context.Companies.Add(new Company { Name = "Google" });
            context.Companies.Add(new Company { Name = "Apple" });
        }
    }
}

 

Now we need to set things up so that the database initializer runs each time the application starts (at least, during "development").

Update the Program.cs file as follows. Note you need to add a reference to System.Data.Entity as well as your Models namespace in your using statements:

Update Program.cs to Run  the Database Initializer:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Owin.Hosting;
 
// Add reference to:
using System.Data.Entity;
using MinimalOwinWebApiSelfHost.Models;
 
namespace MinimalOwinWebApiSelfHost
{
    class Program
    {
        static void Main(string[] args)
        {
            // Set up and seed the database:
            Console.WriteLine("Initializing and seeding database...");
            Database.SetInitializer(new ApplicationDbInitializer());
            var db = new ApplicationDbContext();
            int count = db.Companies.Count();
            Console.WriteLine("Initializing and seeding database with {0} company records...", count);
 
            // 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();
        }
    }
}

 

Last, let's add a [Key] attribute to the Id in our Company class, so that EF will know we want the to be an Auto-incrementing int key. Note that you need to add a reference to System.ComponentModel.DataAnnotations in your using statements:

Update the Company Class with a [Key] Attribute:
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; }
    }
}

 

Update the Controller to Consume the Database and Use Async Methods

Now we need to make some changes to our CompaniesController. Previously, we were working with a list as a mock datastore. Now let's update our controller methods to work with an actual database. Also, we will now use async methods.

Note that we need to add a reference to System.Data.Entity in our using statements.

Update Controller Methods to Consume Database and Use Async/Await:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Net.Http;
using MinimalOwinWebApiSelfHost.Models;
 
// Add these usings:
using System.Data.Entity;
 
namespace MinimalOwinWebApiSelfHost.Controllers
{
    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();
        }
    }
}

 

Last, we need to make a couple minor changes to our client application, since we are now working with a database which will insert auto-incrementing integer Id's.

Update Api Client Application

We only need to change a single line here, where we previously provided a new Id value when adding a new company. Change the highlighted line as follows:

Don't Pass a Value for the new Id when Adding a Record:
Console.WriteLine("Add a new company...");
var result = companyClient.AddCompany(new Company 
    { 
        Name = string.Format("New Company #{0}", nextId) 
    });
WriteStatusCodeResult(result);

 

Now all we are doing is using the next Id as part of a hacked together naming scheme (and this is NOT a good way to get hold of the next Id from your database, either . . .).

Running the Self-Hosted Web Api with the Database

If we have done everything correctly, we can spin up the Web Api application, and then run the Client application, and see what happens. If all went well, our console output should be basically the same as before:

Console Output from Starting the Web Api Application:

console-output-web-api-startup-with-database

Likewise, when we run the client application, our console output should be essentially the same as before, except this time the Web Api is fetching and saving to the SQL CE database instead of an in-memory list:

Console Output from the Web Api Client Application at Startup:

console-output-client-startup-with-database

Next Steps

In this post, we've seen how to assemble a very simple, and minimal ASP.NET Web Api application in a self-hosted scenario, without IIS, and without taking a dependency on the heavy weight System.Web library. We took advantage of the OWIN/Katana middleware pipeline, and we saw how to "hook" the Web Api components into the host/server interaction.

Next, we will investigate how we can apply these same concepts to build out a minimal footprint Web Api while still hosting in an IIS environment, and we will see how to bring ASP.NET Identity in to add some authentication and authorization functionality to the picture.

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

Additional Resources and Items of Interest

 

Posted on January 11 2015 05:13 PM by jatten     

Comments (2)

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