Token Based Authentication using ASP.NET Web API 2, Owin, and Identity

Last week I was looking at the top viewed posts on my blog and I noticed that visitors are interested in the authentication part of ASP.NET Web API, CORS Support, and how to authenticate users in single page applications built with AngularJS using token based approach.

So I decided to compile mini tutorial of three five posts which covers and connects those topics. In this tutorial we’ll build SPA using AngularJS for the front-end, and ASP.NET Web API 2, Owin middleware, and ASP.NET Identity for the back-end.


The demo application can be accessed on (http://ngAuthenticationWeb.azurewebsites.net). The back-end API can be accessed on (http://ngAuthenticationAPI.azurewebsites.net/) and both are hosted on Microsoft Azure, for learning purposes feel free to integrate and play with the back-end API with your front-end application. The API supports CORS and accepts HTTP calls from any origin. You can check the source code for this tutorial on Github.

AngularJS Authentication

 

Token Based Authentication

As I stated before we’ll use token based approach to implement authentication between the front-end application and the back-end API, as we all know the common and old way to implement authentication is the cookie-based approach were the cookie is sent with each request from the client to the server, and on the server it is used to identify the authenticated user.

With the evolution of front-end frameworks and the huge change on how we build web applications nowadays the preferred approach to authenticate users is to use signed token as this token sent to the server with each request, some of the benefits for using this approach are:

  • Scalability of Servers: The token sent to the server is self contained which holds all the user information needed for authentication, so adding more servers to your web farm is an easy task, there is no dependent on shared session stores.
  • Loosely Coupling: Your front-end application is not coupled with specific authentication mechanism, the token is generated from the server and your API is built in a way to understand this token and do the authentication.
  • Mobile Friendly: Cookies and browsers like each other, but storing cookies on native platforms (Android, iOS, Windows Phone) is not a trivial task, having standard way to authenticate users will simplify our life if we decided to consume the back-end API from native applications.

What we’ll build in this tutorial?

The front-end SPA will be built using HTML5, AngularJS, and Twitter Bootstrap. The back-end server will be built using ASP.NET Web API 2 on top of Owin middleware not directly on top of ASP.NET; the reason for doing so that we’ll configure the server to issue OAuth bearer token authentication using Owin middleware too, so setting up everything on the same pipeline is better approach. In addition to this we’ll use ASP.NET Identity system which is built on top of Owin middleware and we’ll use it to register new users and validate their credentials before generating the tokens.

As I mentioned before our back-end API should accept request coming from any origin, not only our front-end, so we’ll be enabling CORS (Cross Origin Resource Sharing) in Web API as well for the OAuth bearer token provider.

Use cases which will be covered in this application:

  • Allow users to signup (register) by providing username and password then store credentials in secure medium.
  • Prevent anonymous users from viewing secured data or secured pages (views).
  • Once the user is logged in successfully, the system should not ask for credentials or re-authentication for the next 24 hours 30 minutes because we are using refresh tokens.

So in this post we’ll cover step by step how to build the back-end API, and on the next post we’ll cover how we’ll build and integrate the SPA with the API.

Enough theories let’s get our hands dirty and start implementing the API!

Building the Back-End API

Step 1: Creating the Web API Project

In this tutorial I’m using Visual Studio 2013 and .Net framework 4.5, you can follow along using Visual Studio 2012 but you need to install Web Tools 2013.1 for VS 2012 by visiting this link.

Now create an empty solution and name it “AngularJSAuthentication” then add new ASP.NET Web application named “AngularJSAuthentication.API”, the selected template for project will be as the image below. Notice that the authentication is set to “No Authentication” taking into consideration that we’ll add this manually.

Web API Project Template

Step 2: Installing the needed NuGet Packages:

Now we need to install the NuGet packages which are needed to setup our Owin server and configure ASP.NET Web API to be hosted within an Owin server, so open NuGet Package Manger Console and type the below:

The  package “Microsoft.Owin.Host.SystemWeb” is used to enable our Owin server to run our API on IIS using ASP.NET request pipeline as eventually we’ll host this API on Microsoft Azure Websites which uses IIS.

Step 3: Add Owin “Startup” Class

Right click on your project then add new class named “Startup”. We’ll visit this class many times and modify it, for now it will contain the code below:

What we’ve implemented above is simple, this class will be fired once our server starts, notice the “assembly” attribute which states which class to fire on start-up. The “Configuration” method accepts parameter of type “IAppBuilder” this parameter will be supplied by the host at run-time. This “app” parameter is an interface which will be used to compose the application for our Owin server.

The “HttpConfiguration” object is used to configure API routes, so we’ll pass this object to method “Register” in “WebApiConfig” class.

Lastly, we’ll pass the “config” object to the extension method “UseWebApi” which will be responsible to wire up ASP.NET Web API to our Owin server pipeline.

Usually the class “WebApiConfig” exists with the templates we’ve selected, if it doesn’t exist then add it under the folder “App_Start”. Below is the code inside it:

Step 4: Delete Global.asax Class

No need to use this class and fire up the Application_Start event after we’ve configured our “Startup” class so feel free to delete it.

Step 5: Add the ASP.NET Identity System

After we’ve configured the Web API, it is time to add the needed NuGet packages to add support for registering and validating user credentials, so open package manager console and add the below NuGet packages:

The first package will add support for ASP.NET Identity Owin, and the second package will add support for using ASP.NET Identity with Entity Framework so we can save users to SQL Server database.

Now we need to add Database context class which will be responsible to communicate with our database, so add new class and name it “AuthContext” then paste the code snippet below:

As you can see this class inherits from “IdentityDbContext” class, you can think about this class as special version of the traditional “DbContext” Class, it will provide all of the Entity Framework code-first mapping and DbSet properties needed to manage the identity tables in SQL Server. You can read more about this class on Scott Allen Blog.

Now we want to add “UserModel” which contains the properties needed to be sent once we register a user, this model is POCO class with some data annotations attributes used for the sake of validating the registration payload request. So under “Models” folder add new class named “UserModel” and paste the code below:

Now we need to add new connection string named “AuthContext” in our Web.Config class, so open you web.config and add the below section:

Step 6: Add Repository class to support ASP.NET Identity System

Now we want to implement two methods needed in our application which they are: “RegisterUser” and “FindUser”, so add new class named “AuthRepository” and paste the code snippet below:

What we’ve implemented above is the following: we are depending on the “UserManager” that provides the domain logic for working with user information. The “UserManager” knows when to hash a password, how and when to validate a user, and how to manage claims. You can read more about ASP.NET Identity System.

Step 7: Add our “Account” Controller

Now it is the time to add our first Web API controller which will be used to register new users, so under file “Controllers” add Empty Web API 2 Controller named “AccountController” and paste the code below:

By looking at the “Register” method you will notice that we’ve configured the endpoint for this method to be “/api/account/register” so any user wants to register into our system must issue HTTP POST request to this URI and the pay load for this request will contain the JSON object as below:

Now you can run your application and issue HTTP POST request to your local URI: “http://localhost:port/api/account/register” or you can try the published API using this end point: http://ngauthenticationapi.azurewebsites.net/api/account/register if all went fine you will receive HTTP status code 200 and the database specified in connection string will be created automatically and the user will be inserted into table “dbo.AspNetUsers”.

Note: It is very important to send this POST request over HTTPS so the sensitive information get encrypted between the client and the server.

The “GetErrorResult” method is just a helper method which is used to validate the “UserModel” and return the correct HTTP status code if the input data is invalid.

Step 8: Add Secured Orders Controller

Now we want to add another controller to serve our Orders, we’ll assume that this controller will return orders only for Authenticated users, to keep things simple we’ll return static data. So add new controller named “OrdersController” under “Controllers” folder and paste the code below:

Notice how we added the “Authorize” attribute on the method “Get” so if you tried to issue HTTP GET request to the end point “http://localhost:port/api/orders” you will receive HTTP status code 401 unauthorized because the request you send till this moment doesn’t contain valid authorization header. You can check this using this end point: http://ngauthenticationapi.azurewebsites.net/api/orders

Step 9: Add support for OAuth Bearer Tokens Generation

Till this moment we didn’t configure our API to use OAuth authentication workflow, to do so open package manager console and install the following NuGet package:

After you install this package open file “Startup” again and call the new method named “ConfigureOAuth” as the first line inside the method “Configuration”, the implemntation for this method as below:

Here we’ve created new instance from class “OAuthAuthorizationServerOptions” and set its option as the below:

  • The path for generating tokens will be as :”http://localhost:port/token”. We’ll see how we will issue HTTP POST request to generate token in the next steps.
  • We’ve specified the expiry for token to be 24 hours, so if the user tried to use the same token for authentication after 24 hours from the issue time, his request will be rejected and HTTP status code 401 is returned.
  • We’ve specified the implementation on how to validate the credentials for users asking for tokens in custom class named “SimpleAuthorizationServerProvider”.

Now we passed this options to the extension method “UseOAuthAuthorizationServer” so we’ll add the authentication middleware to the pipeline.

Step 10: Implement the “SimpleAuthorizationServerProvider” class

Add new folder named “Providers” then add new class named “SimpleAuthorizationServerProvider”, paste the code snippet below:

As you notice this class inherits from class “OAuthAuthorizationServerProvider”, we’ve overridden two methods “ValidateClientAuthentication” and “GrantResourceOwnerCredentials”. The first method is responsible for validating the “Client”, in our case we have only one client so we’ll always return that its validated successfully.

The second method “GrantResourceOwnerCredentials” is responsible to validate the username and password sent to the authorization server’s token endpoint, so we’ll use the “AuthRepository” class we created earlier and call the method “FindUser” to check if the username and password are valid.

If the credentials are valid we’ll create “ClaimsIdentity” class and pass the authentication type to it, in our case “bearer token”, then we’ll add two claims (“sub”,”role”) and those will be included in the signed token. You can add different claims here but the token size will increase for sure.

Now generating the token happens behind the scenes when we call “context.Validated(identity)”.

To allow CORS on the token middleware provider we need to add the header “Access-Control-Allow-Origin” to Owin context, if you forget this, generating the token will fail when you try to call it from your browser. Not that this allows CORS for token middleware provider not for ASP.NET Web API which we’ll add on the next step.

Step 11: Allow CORS for ASP.NET Web API

First of all we need to install the following NuGet package manger, so open package manager console and type:

Now open class “Startup” again and add the highlighted line of code (line 8) to the method “Configuration” as the below:

Step 12: Testing the Back-end API

Assuming that you registered the username “Taiseer” with password “SuperPass” in the step below, we’ll use the same username to generate token, so to test this out open your favorite REST client application in order to issue HTTP requests to generate token for user “Taiseer”. For me I’ll be using PostMan.

Now we’ll issue a POST request to the endpoint http://ngauthenticationapi.azurewebsites.net/token the request will be as the image below:

OAuth Token Request

Notice that the content-type and payload type is “x-www-form-urlencoded” so the payload body will be on form (grant_type=password&username=”Taiseer”&password=”SuperPass”). If all is correct you’ll notice that we’ve received signed token on the response.

As well the “grant_type” Indicates the type of grant being presented in exchange for an access token, in our case it is password.

Now we want to use this token to request the secure data using the end point http://ngauthenticationapi.azurewebsites.net/api/orders so we’ll issue GET request to the end point and will pass the bearer token in the Authorization header, so for any secure end point we’ve to pass this bearer token along with each request to authenticate the user.

Note: that we are not transferring the username/password as the case of Basic authentication.

The GET request will be as the image below:

Token Get Secure Resource

If all is correct we’ll receive HTTP status 200 along with the secured data in the response body, if you try to change any character with signed token you directly receive HTTP status code 401 unauthorized.

Now our back-end API is ready to be consumed from any front end application or native mobile app.

Update (2014-08-11) Thanks for Attila Hajdrik for forking my repo and updating it to use MongoDb instead of Entity Framework, you can check it here.

You can check the demo application, play with the back-end API for learning purposes (http://ngauthenticationapi.azurewebsites.net), and check the source code on Github.

Follow me on Twitter @tjoudeh

References

Comments

  1. Adrian Rocke says

    Thanks for the great tutorial! It’s nice to be able to build some of this myself so I can actually understand what is going on instead of having visual studio generate everything automatically.

  2. says

    Thanks Taiseer for the great post.

    I’ve learned a lot on the ASP.NET Identity in this post and others too.
    I have a little concern. I am not using EF and I have my own data layer using ADO or Enterprise Library. I wonder how I can customize Owin to use other frameworks rather than EF.

    • says

      Hi Benham,
      You can use ADO.NET for sure to implement token based authentication, there is no need for use ASP.NET Identity at all, if you noticed I’m using Identity to create users and verify that username/password are correct, you can create your own Repository classes which shields ADO.NET from your business logic. if you need further help let me know.

  3. Eric Eskildsen says

    To get CORS to work on the token endpoint once I changed the API to run on a subdomain, I had to move the line “app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);” to be first in the OWIN configuration in Startup.cs, and then remove the line “context.OwinContext.Response.Headers.Add(“Access-Control-Allow-Origin”, new[] { “*” });” from the GrantResourceOwnerCredentials method. See FancyNancy’s comment on this StackOverflow question: http://stackoverflow.com/questions/26980271/web-api-2-preflight-cors-request-for-bearer-token

  4. Eric Eskildsen says

    To add to my last comment, I also had to add the line “config.EnableCors(new EnableCorsAttribute(“*”, “*”, “*”));” to my WebApiConfig class’s Register method to enable CORS for Web API controllers.

  5. says

    Thank you for your efforts on this. Just got an NHibernate implementation up and running, working a treat – no problems encountered a sign of a good how-to!

  6. Gayan says

    Hi Taiseer, Thank you very much for this article and I actually implemented it successfully. Had to do some tweaks as we have our own layer for validating credentials. But I have a question: Once the token’s life time is expired, how does the client know it so that it can request a new token? Appreciate your help.

  7. Teo says

    Finally a great article! And not one where you press some buttons, everything works magically, and if you want to change something – well, to bad, you got no idea cause everything was magic :)

      • Ravindra says

        So I have below infrastructure
        1) Web API and MongoDB as DB and used repository pattern for CRUD operations
        2) 2 websites written in Angular – accessing the above WebAPI
        3) Android App – Uses the same WebAPI
        4) Another web site written in Java with spring framework

        I want to implement a single authentication service for all the clients i.e. 2 sites and the app, so I followed the series http://bitoftech.net/2015/01/21/asp-net-identity-2-with-asp-net-web-api-2-accounts-management/comment-page-1/#comments and was successfully able to implement identity for my API I am trying to make it authentication work for my Angular web sites through the API, however I am not sure if is going to work for my other clients (Android app and Java based website). That’s the reason I wanted to understand if there is any difference between this series and the other one. Any suggestions ?

  8. Ali says

    Hi Taiseer, i enjoy read your article is very well explained. Im totally new on this, i have a business logic already created with FoxPro databases (and this manage the users and password) so i don’t know what to do now because you use the DB Context with EEF and i don’t have any idea that how to replace this part of your excellent tutorial. can you help me?

    • says

      Hi Ali,
      I do not have experience in FoxPro so it is hard to help here. But you can keep using it and implement the token authentication, You can create your own repository layer and expose the methods needed to do account verification (login).

  9. FKutsche says

    Hey,
    can you give a brief explanation on how to extend the user identity? I am a bit stuck on that. I just want to store more information about the user in my database. It does not have to be done with the registration. Just an extension to the model. The rest should be easy

  10. FKutsche says

    Hey,
    your solution works very fine for me, but do you have a clean solution for extending the user? I just want to store more information like first name, address, etc. This does not have to be done with the registration. I’m struggling a little bit because I want to have one class for the user from which I can get all information.

    Do you have any suggestions on doing that with your approach?

  11. Shoaib says

    Hi…Taiseer Joudeh,
    I’d successfully implement the Owin token based authentication and Refresh Token feature but I want to implement the concept like,

    When user get access token for 20 minutes and he/she is idle for the first 15 minutes and then makes any request, then token have only 5 minutes remaining to expires, but whenever he/she makes any request then access token expire time automatically readjusted to next 20 minutes

    Means when authentication server receives any request from front-end application then access token expire time must be extended and readjusted to 20 minutes from the last request just like in session concept…

  12. adri says

    Really great tutorial! Thanks a lot!
    Is it possible to run the API on OWIN self-host instead of IIS? And is it possible to change the database to an existing MySQL server? Thanks again.

      • adri says

        Is it tricky to switch to OWIN self host? And you mentioned https to ensure the sensitive information get encrypted between the client and the server during resgistration. What is a good approach for this? Do I need certificated for this?

  13. says

    Taiseer,

    Amazing series of articles! I have a question about multi-tenancy. I have multiple applications, and I have users which will have different roles based on the application they are logging in from – for example, User A is an admin on Application A, an author on Application B, and should not have access to Application C. How would I extend this to enable such a system? I feel like your approach gets me almost there, but I’m just not sure about storage, and should I append to the token or create a different routing for the Api based on application?

    • says

      Hi Brian

      Thanks for your message, I recommend you to check Identity Server to implement this approach, you need a stand alone Identity provider where you can define your clients and create different scopes for each client, extending my basic implementation to support your scenario will be very complicated.

      The documentation for Identity Server is really good now and it is easy to implement your IDP so you can define custom roles per client. Let me know if you need help in this.

      • says

        Taiseeer, Thanks for your quick reply. I’m going to try extending IdentityRole to add a new column, “domain”. This way each application will have it’s own set of roles. I’ll let you know if it works. :)

        If not, I’ll look into Identity Server. Thanks again!

Leave a Reply