Step by step article to implement Token Based Authentication using ASP.NET Web API 2, Owin, and Identity

Today I will show you how you can implement token based Authentication in asp.net web api using OWNIN and identity. We're not storing token in database but OWIN will take care of it's expiry time and validity.

Get Started

Open Visual studio and add a new web api project. token based Authentication in asp.net web api using OWNIN and identity

Installing the needed NuGet Packages

We need to install related nuget packages to make web api alive.

  • Install-Package Microsoft.AspNet.WebApi.Owin
  • Install-Package Microsoft.Owin.Host.SystemWeb

Add Startup class

We need to add a startup class in which we actually write our token genration code and also define end point of our application from where we get token.

Right click on your project and add a new class. name it startup.cs. and paste below code in that file.

                    using Microsoft.Owin;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
[assembly: OwinStartup(typeof(AngularJSAuthentication.API.Startup))]
namespace AngularJSAuthentication.API
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();
            WebApiConfig.Register(config);
            app.UseWebApi(config);
        }
    }
}

WebApiConfig file

Now move to WebApiConfig file located under the App_start folder. if file not exist you can add personally. Paste below code in your WebApiConfig file.

                public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
 
            // Web API routes
            config.MapHttpAttributeRoutes();
 
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
 
            var jsonFormatter = config.Formatters.OfType().First();
            jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        }
    }

Work with Asp.net identity

We register our user with asp.net identity and on each request we use identity object to authorize user. Now add some nuget packages related to asp.net identity.

  • Install-Package Microsoft.AspNet.Identity.Owin -Version 2.0.1
  • Install-Package Microsoft.AspNet.Identity.EntityFramework -Version 2.0.1

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:

    public class AuthContext : IdentityDbContext
    {
        public AuthContext()
            : base("AuthContext")
        {
 
        }
    }

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:

                public class UserModel
    {
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }
 
        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }
 
        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }
    }

Add new connection string name it AuthContext. you add this connection string in your config file

                
                
  

Add simple Repository class to support ASP.NET Identity System

    public class AuthRepository : IDisposable
    {
        private AuthContext _ctx;
        private UserManager _userManager;
        public AuthRepository()
        {
            _ctx = new AuthContext();
            _userManager = new UserManager(new UserStore(_ctx));
        }
        public async Task RegisterUser(UserModel userModel)
        {
            IdentityUser user = new IdentityUser
            {
                UserName = userModel.UserName
            };
            var result = await _userManager.CreateAsync(user, userModel.Password);
            return result;
        }
        public async Task FindUser(string userName, string password)
        {
            IdentityUser user = await _userManager.FindAsync(userName, password);
            return user;
        }
        public void Dispose()
        {
            _ctx.Dispose();
            _userManager.Dispose();
        }
    }

Add first web api controller

                [RoutePrefix("api/Account")]
    public class AccountController : ApiController
    {
        private AuthRepository _repo = null;
 
        public AccountController()
        {
            _repo = new AuthRepository();
        }
 
        // POST api/Account/Register
        [AllowAnonymous]
        [Route("Register")]
        public async Task Register(UserModel userModel)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
 
            IdentityResult result = await _repo.RegisterUser(userModel);
 
            IHttpActionResult errorResult = GetErrorResult(result);
 
            if (errorResult != null)
            {
                return errorResult;
            }
 
            return Ok();
        }
 
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _repo.Dispose();
            }
 
            base.Dispose(disposing);
        }
 
        private IHttpActionResult GetErrorResult(IdentityResult result)
        {
            if (result == null)
            {
                return InternalServerError();
            }
 
            if (!result.Succeeded)
            {
                if (result.Errors != null)
                {
                    foreach (string error in result.Errors)
                    {
                        ModelState.AddModelError("", error);
                    }
                }
 
                if (ModelState.IsValid)
                {
                    // No ModelState errors are available to send, so just return an empty BadRequest.
                    return BadRequest();
                }
 
                return BadRequest(ModelState);
            }
 
            return null;
        }
    }

Now Register a new user in your database by using Register Route from your Controller. You need a web client for that purpose. i recomend to download post man from which you can send post and get calls to your webapi.

                {
  "userName": "Test",
  "password": "123456",
  "confirmPassword": "123456"
}

Final touch

Now we need to add token based logic in our project. so add nuget package which help us to genrate token based Authentication

  • Install-Package Microsoft.Owin.Security.OAuth -Version 2.1.0

Now open Startup class and add below code in that class

                public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureOAuth(app);
	    //Rest of code is here;
        }
 
        public void ConfigureOAuth(IAppBuilder app)
        {
            OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
                Provider = new SimpleAuthorizationServerProvider()
            };
 
            // Token Generation
            app.UseOAuthAuthorizationServer(OAuthServerOptions);
            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
 
        }
    }

Implement the “SimpleAuthorizationServerProvider” class

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

                public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            context.Validated();
        }
 
        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
 
            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
 
            using (AuthRepository _repo = new AuthRepository())
            {
                IdentityUser user = await _repo.FindUser(context.UserName, context.Password);
 
                if (user == null)
                {
                    context.SetError("invalid_grant", "The user name or password is incorrect.");
                    return;
                }
            }
 
            var identity = new ClaimsIdentity(context.Options.AuthenticationType);
            identity.AddClaim(new Claim("sub", context.UserName));
            identity.AddClaim(new Claim("role", "user"));
 
            context.Validated(identity);
 
        }
    }

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:

  • Install-Package Microsoft.Owin.Cors -Version 2.1.0

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

                public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();
 
            ConfigureOAuth(app);
 
            WebApiConfig.Register(config);
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            app.UseWebApi(config);
 
        }

Testing application

Assuming that you registered the username “Test” with password “123456” 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 “Test”. For me I’ll be using PostMan.

Result

If all goes well you will see a token containg large string combination of characters and digits. you will receive this token in response of web api.