Home Using OWIN to self-host Web API and secure endpoints
Post
Cancel

Using OWIN to self-host Web API and secure endpoints

In this post we are going to talk a little bit about OWIN. What is it, how can we use it with ASP.NET Web API to expose API endpoints, as well as how to secure those endpoints.

The application uses OWIN to self-host the Web API as well as ASP.NET Identity as underlying membership mechanism. Users can fetch public data from /api/people endpoint, as well as secured private data from /api/user endpoint. The latter one is to demonstrate security in Web API.

Brief discussion on OWIN

OWIN stands for Open Web Interface for .NET. It defines a standard communication interface between .NET web servers and web applications, proving a specification to work with. This specification can be found here.
It enables implementation of functionality without having to take dependency on the hosting framework, with this abstraction being specified in many other web platforms such Ruby, Node.js or Python.

OWIN specification defines parts for:

  • Host
  • Server
  • Middleware
  • Application

Host is a process. It can be a windows application, a windows service, anything that is responsible of providing a runtime platform for incoming requests.
Into the host, is the server, which accepts HTTP requests and sends responses using the OWIN runtime. Server and Application communicate through the OWIN pipeline, which makes this possible by the use of a number of middlewares that are registered on it.
Lastly, Application is implemented in a framework such as ASP.NET Web API or NancyFx and generates a response back to the client, which travels through the pipeline, passing all intermediate middleware, to the server and from server to the client.

OWIN Katana is the Microsoft implementation of OWIN specification. The package Microsoft.Owin contains the Katana implementation.
This is the exact implementation I am going to demonstrate in the next lines.
So, next up, the Katana implementation is going to be used to self-host an ASP.NET Web API as well as some middleware to secure API endpoints.

Setup

I used Visual Studio and made a new Console Application. The application structure is like so:

People.SelfHostedApi
|--App_Start
|----IdentityConfig.cs
|----WebApiRouteConfig.cs
|--Controllers
|----PeopleController.cs
|----UserController.cs
|--Database
|----ApplicationDbContext.cs
|--Infrastructure
|----Formatters
|------BrowserFormatter.cs
|--Migrations
|----Configuration.cs
|--Models
|----Person.cs
|--Security
|----CustomAuthorizationServerProvider.cs
|--App.config
|--Program.cs
|--Startup.cs

 

Packages needed

Through nuget package manager and I installed the following packages:

  • Microsoft.AspNet.WebApi.OwinSelfHost
  • Microsoft.Owin.Security.OAuth
  • Microsoft.AspNet.Identity.Owin
  • Microsoft.AspNet.Identity.EntityFramework

With all these, the setup is done. It's time to proceed to code.

Hosting the API

I need a way to host the application. Then I remember the parts of the OWIN specification from before. Regarding the hosting, I need to build the process that is running the application. This will be a Windows Console Application. In the Program.cs, in Main method the API is kicked-off by using the WebApp class, calling the Start method, which takes the URL of the application and an entry point of the OWIN configuration (Startup class).

class Program
    {
        static void Main(string[] args)
        {
            const string url = "http://localhost:3001";
            using (WebApp.Start<Startup>(url))
            {
                Console.WriteLine("Application deployed and hosted in {0}", url);
                Console.WriteLine("Press any key to terminate...");
                Console.ReadLine();
            }
        }
    }

I am wrapping the call of the Start method in a using statement, as this is a disposable entity and I call the Console.ReadLine method inside its body in order to keep the application open.

Nothing else to see here, let's move to the juicy bits of the Startup class.

public class Startup
    {
        public static void Configuration(IAppBuilder app)
        {
            var configuration = new HttpConfiguration();
            WebApiRouteConfig.Register(configuration);
            app.UseWebApi(configuration);
        }
    }

A class like this, that implements the OWIN Katana must have a static void method with the name Configuration, and take a single parameter of type IAppBuilder.
See the UseWebApi extension method? These kind of methods are nothing more than extensions to the IAppBuilder.Use method, which is used to add middleware into the OWIN pipeline. In fact, OWIN is all about the pipeline. The components that are registered into it know nothing about each other, but they manage to work together, by walking down the road in the pipeline until the final component is reached. Then, up they go back to the client, climbing the pipeline once again, bottom-up.

First thing first, the Server part is now implemented. The OWIN Katana acts as a server, as it can accept HTTP requests and send responses, even without using the Web API middleware, you just need to add middleware to handle requests and responses.
Where is the Application though? For this part, most critical is to create a new HttpConfiguration instance. HttpConfiguration controls whatever has to do with routing, serializers, formatters, etc. It is a dependency for the Web API middleware, UseWebApi extension method, which is putting the last piece in the OWIN puzzle, the Application part.
With all these in place, we have an application that can receive HTTP traffic, process the requests, and reply back to the client with appropriate HTTP responses.
Concluding with the Web API configuration, I register the routes for Web API to handle by calling the WebApiRouteConfig.Register, pretty much standard routine, no need to go there.

Le'ts create a simple ApiController and expose some endpoints to see this in action.

This is a simple controller, that returns a list of people or finds a person by id.

public class PeopleController : ApiController
    {
        private readonly List<Person> _people;

        public PeopleController()
        {
            _people = new List<Person>
            {
                new Person { Age = 15, Id = 1, Name = "John Doe"},
                new Person { Age = 22, Id = 2, Name = "Jane Doe"}
            };
        }

        public IHttpActionResult Get()
        {
            return Ok(_people);
        }

        public IHttpActionResult Get(int id)
        {
            var person = _people.Find(p => p.Id == id);
            return Ok(person);
        }
    }

Running the application, I test it by running a Postman instance, hitting the GET and GET/{id} endpoints.

Listing 1-1. GET /api/people
screenshot_1

Listing 1-2. GET /api/people/2
screenshot_2

That's a fairly simple example using an in-memory collection of people. If we wanted to fetch those data from a different kind of store (database, XML file, CSV file, whatever, it doesn't matter) we'd only have to implement a store and use its methods.

Securing endpoints and using ASP.NET Identity

In order to make this more interesting, I am going to add another controller which will fetch the current authenticated user details and return them back to the client. Also, people data will be persisted in a database, which needs to be accessed in order to fetch them, so that said, I'm going to make use of the ASP.NET Identity features for the features described.
I just create a class Person to represent the entity.

public class Person
    {
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

And a simple database context.

public class ApplicationDbContext: IdentityDbContext<IdentityUser>
    {
        public ApplicationDbContext(): base("DefaultConnection", throwIfV1Schema: false) { }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }

        public DbSet<Person> People { get; set; }
    }

Nothing fancy. Just a quick note on IdentityDbContext. It is located at Microsoft.AspNet.Identity.EntityFramework assembly and it an implementation of the DbContext class which gives you access to the underlying context (database).  This class manipulates the Entity Framework model internally so it sets proper tables, proper relationships to manage users, roles, claims, etc. For creating your own store you need to derive from that class.
With Entity Framework Code First Migrations I then initialize the  store with the schema and possible seed values (I have already done that, refer to the code on Github for more).
Finally I added a custom UserManager in order to initialize the custom store, which uses the ApplicationDbContext I made earlier, again I won't go through that now.

I need to go to some modifications now in existing code, as well as bring in life the UserController. Let's go first with the controllers, then to Startup class and finally to a simple custom authorization server provider implementation.

UserController

[Authorize]
    public class UserController : ApiController
    {
        private ApplicationUserManager _userManager;
        public ApplicationUserManager UserManager => 
            _userManager ?? (_userManager = Request.GetOwinContext().GetUserManager<ApplicationUserManager>());

        public IHttpActionResult Get()
        {
            var id = User.Identity.GetUserId();
            var user = UserManager.FindById(id);
            return Ok(user);
        }
    }

In this controller, I have only one simple GET method which returns all details about a logged-in user, for demonstration purposes.
The controller is decorated with the AuthorizeAttribute to enforce Authentication.
The ApplicationUserManager is the one I created earlier. In order to get it, I get the OwinContext associated with the HttpRequestMessage, using the GetUserManager extension method of IOwinContext, to get the ApplicationUserManager instance, registered to OwinContext (see below). Using C# 6 Expression Bodied property for UserManager property.
If a user is authenticated, the /api/user endpoint is accessible. Depending on the claims registered on the current context, the IPrincipal.User is populated, along with the IIdentity.Identity. These properties belong to the System.Security namespace. The Microsoft.AspNet.Identity package implements some extension methods on them, more specifically on IIdentity interface, which are very useful, methods like GetUserId and GetUserName which fetch the user id or username for the current authenticated context. Having the userId or username we can query the AspNet.Users table through the UserManager instance and fetch the associated user.

PeopleController

public class PeopleController : ApiController
    {
        private readonly ApplicationDbContext _context;

        public PeopleController()
        {
            _context = new ApplicationDbContext();
        }

        public IHttpActionResult Get()
        {
            var people = _context.People.ToList();
            return Ok(people);
        }

        public IHttpActionResult Get(int id)
        {
            var person = _context.People.Find(id);
            return Ok(person);
        }
    }

The highlighted lines in code above are the changes in the PeopleController for fetching data from the database. Nothing fancy here either, I just need a reference to ApplicationDbContext in order to communicate with the underlying store to fetch people data.
Note that this is not the recommended way to introduce the ApplicationDbContext in PeopleController. This leads to coupling and violates the 'D' of SOLID. Also, this code is not testable and we are going to tackle this subject in future posts. To make this solution more elegant, the dependency should be passed through the constructor, in an abstract format, as an interface, using a DI container.

Startup.Configuration

public class Startup
    {
        public static void Configuration(IAppBuilder app)
        {
            app.CreatePerOwinContext<ApplicationDbContext>(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

            var configuration = new HttpConfiguration();
            WebApiRouteConfig.Register(configuration);

            app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
                Provider = new CustomAuthorizationServerProvider()
            });
            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

            app.UseWebApi(configuration);
        }
    }

I added additional code to Configuration method, essentially using more middleware for the OWIN pipeline. These middleware as stated before, doesn't really know about each other, they are just registered in the pipeline, doing work on incoming requests, then delegating the process to the next in the pipeline and  finally they individually handle the response back to the client.

UseOAuthAuthorizationServer just creates an authorization server and knows nothing about how you implement your application, it doesn't care about your endpoints, it doesn't care about your routes, it doesn't care about content. All it cares is to create, manage, invalidate tokens, as well as authenticating requests.
OAuthBearerAuthentication doesn't care about the authorization server or the Web API, it cares only about tokens in your request header.
Yet, all these work wonderfully together. That's the magic with OWIN components. They plug-in to the OWIN pipeline, they do their thing and then they pass control to the next one in the pipeline.

How about these weird CreatePerOwinContext<T> you might ask, what is their purpose? This is an extension on IAppBuilder which registers a callback to instantiate a type of T on OWIN context, which is available once per request. In the example above, I register the database context (ApplicationDbContext which derives from IdentiyDbContext) so I can have access to the database instance if I wanted to, as well as to the ApplicationUserManager, which is essentially an implementation of UserManager<T>, an entity that provides enough abstractions for a developer to manage the AspNet.Users table, of ASP.NET Identity.

Note that we can customize the authorization server to our hearts content, by providing details on the token endpoint, use of HTTPS, expiration of the issued token, custom implementation of an authorization provider and much more. For more info relate to MSDN documentation.
I have added a custom implementation of an authorization server provider, which is fairly simple, it just validates a token based on the username and password provided by an HTTP POST request at /token endpoint.

CustomAuthorizationServerProvider

public class CustomAuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
        public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            context.Validated();
            return Task.FromResult(0);
        }

        public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            context.OwinContext.Response.Headers.Add(new KeyValuePair<string, string[]>("Access-Control-Allow-Origin", new[] { "*" }));

            var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
            var user = userManager.Find(context.UserName, context.Password);
            if (user == null)
            {
                context.SetError("invalid_grant", "Username and password do not match.");
                return Task.FromResult(0);
            }

            var identity = new ClaimsIdentity(context.Options.AuthenticationType);
            identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));
            identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));

            context.Validated(identity);
            return Task.FromResult(0);

        }
    }

Please note this code is for demonstration purposes only and should not be used in production. If you really want to implement OAuth in production you need to fully comply with the protocol and implement your logic on authorization server. In coming posts I am going to cover that a little bit more.
I just override two methods of OAuthAuthorizationServerProvider base class. The ValidateClientAuthentication method validates that the origin of the request is a valid "client_id". We don't really care to implement the OAuth specification here, so essentially, every incoming request is validated.
From GrantResourceOwnerCredentials method metadata:

Called when a request to the Token endpoint arrives with a "grant_type" of "password".
This occurs when the user has provided name and password credentials directly
into the client application's user interface, and the client application is using
those to acquire an "access_token" and optional "refresh_token". If the web application
supports the resource owner credentials grant type it must validate the context.Username
and context.Password as appropriate. To issue an access token the context.Validated
must be called with a new ticket containing the claims about the resource owner
which should be associated with the access token. The application should take
appropriate measures to ensure that the endpoint isn’t abused by malicious callers.
The default behavior is to reject this grant type. See also http://tools.ietf.org/html/rfc6749#section-4.3.2

As the method states, if we use a grant_type of password, then this method is called. In the code above, I get the Username and Password from the context and validate them against the database, on AspNet.Users. If a match is found, I create a new ClaimsIdentity instance, adding claims about the username and the userId. These will be later available through the IIdentity.Identity.GetUserId or IIdentity.Identity.GetUserName extension methods.
Claims are statements about an entity, in previous example this entity is the user itself. ClaimsIdentity is an implementation of IIdentity, which holds an arbitary number of Claims, which is exactly what I did before, adding the userId and the name in ClaimsIdentity collection.
By calling the OAuthGrantResourceOwnerCredentialsContext.Validated() method, the user entity is authenticated and this information is available in the application context. Now subsequent requests will be authenticated.
If user is not found, I return an "invalid_grant" error back to the client.
Please also note that OAuthAuthorizationServerProvider methods are all asynchronous, so each returns a Task.

Test drive

Let's run the application now, first try the /api/people endpoints.

Listing 1-3. GET /api/people
screenshot_3

Listing 1-4. GET /api/people/2
screenshot_4

Nice, data are fetched from the database for the PeopleController.
Let's see what's up with the UserController, the AuthorizeAttribute takes place there, so we expect to see a 401 Unauthorized response, if we do not provide any token information on HTTP headers.

Listing 1-5. GET /api/user (401)
screenshot_8

We are completely locked out of the /api/user endpoint. The only way to have access is to get a Bearer token and provide it in the subsequent requests in the HTTP Headers. Tokens can be acquired from the /token endpoint, which is a POST action. By providing a payload of x-www-form-urlencoded, passing the grant_type, username and password for the account (grant_type=password&username=name&password=pass), a user essentially gets a Bearer token to use.

Listing 1-6. POST /token
screenshot_6

Now it's time to get back to /api/user and call the endpoint, providing an Authorization header, with the Bearer token I just got previously. If the token is correct, then access will be granted for this resource. Remember, a token is invalid after 30 minutes, so you need to go through the same process again to issue another one, unless you set a RefreshTokenProvider.

Listing 1-7. GET /api/user (200)
screenshot_1

Summary

In this post we briefly touched the surface of OWIN Katana implementation. Use cases where presented about ASP.NET Web API, and self-hosting in OWIN. Also, there was a brief discussion on securing endpoints with a simple token authorization server implementation.
In next posts we will go through unit testing the OWIN pipeline, individual controllers, integration testing and documentation. We will explore different, more concrete security configurations, as well as deployment on Azure.

Code can be found here.

Next post: Fixing the design of this application and writing unit tests

This post is licensed under CC BY 4.0 by the author.

Mocking a class dependency which casts into a derived type using Moq

Unit testing and code coverage for ASP.NET Web API (1/2)

Comments powered by Disqus.