In this article, we are going to explain about Token Based Authentication using ASP.NET Web API 2, Owin, and Identity. As you know that a token is a piece of data created by server, and contains information to identify a particular user and token validity. The token will contain the user’s information, as well as a special token code that user can pass to the server with every method that supports authentication, instead of passing a username and password directly.
What is Token Based Authentication?
Token-based authentication is a security technique that authenticates the users who attempt to log in to a server, a network, or some other secure system, using a security token provided by the server. An authentication is successful if a user can prove to a server that he or she is a valid user by passing a security token. The service validates the security token and processes the user request. After the token is validated by the service, it is used to establish security context for the client, so the service can make authorization decisions or audit activity for successive user requests.
The general concept behind a token-based authentication system is simple. Allow users to enter their username and password in order to obtain a token which allows them to fetch a specific resource – without using their username and password. Once their token has been obtained, the user can offer the token – which offers access to a specific resource for a time period – to the remote site.
What is ASP.NET Web API 2, Owin, and Identity?
This article is about Token Based Authentication using ASP.NET Web API 2, Owin, and Identity. ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. ASP.NET Web API is an ideal platform for building RESTful applications on the .NET Framework. ASP.NET Identity is the reworked, flexible replacement for the old membership system that has been around since ASP.NET 2.0. ASP.NET Identity is more well designed and flexible than the old membership system and uses Owin middleware components for external logins such as Facebook, Google and Twitter.
Building the Back-End API
Step 1: Creating the Web API Project
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.
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: 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); } } }
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:
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<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); } }
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:
public class AuthContext : IdentityDbContext<IdentityUser> { public AuthContext() : base(“AuthContext”) }
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.
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:
public class AuthRepository : IDisposable { private AuthContext _ctx; private UserManager<IdentityUser> _userManager; public AuthRepository() { _ctx = new AuthContext(); _userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(_ctx)); } public async Task<IdentityResult> RegisterUser(UserModel userModel) { IdentityUser user = new IdentityUser { UserName = userModel.UserName }; var result = await _userManager.CreateAsync(user, userModel.Password); return result; } public async Task<IdentityUser> FindUser(string userName, string password) { IdentityUser user = await _userManager.FindAsync(userName, password); return user; } public void Dispose() { _ctx.Dispose(); _userManager.Dispose(); } }
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:
[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<IHttpActionResult> 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; } }
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:
[RoutePrefix(“api/Orders”)] public class OrdersController : ApiController { [Authorize] [Route(“”)] public IHttpActionResult Get() { return Ok(Order.CreateOrders()); } } #region Helpers public class Order { public int OrderID { get; set; } public string CustomerName { get; set; } public string ShipperCity { get; set; } public Boolean IsShipped { get; set; } public static List<Order> CreateOrders() { List<Order> OrderList = new List<Order> { new Order {OrderID = 10248, CustomerName = “Taiseer Joudeh”, ShipperCity = “Amman”, IsShipped = true }, new Order {OrderID = 10249, CustomerName = “Ahmad Hasan”, ShipperCity = “Dubai”, IsShipped = false}, new Order {OrderID = 10250,CustomerName = “Tamer Yaser”, ShipperCity = “Jeddah”, IsShipped = false }, new Order {OrderID = 10251,CustomerName = “Lina Majed”, ShipperCity = “Abu Dhabi”, IsShipped = false}, new Order {OrderID = 10252,CustomerName = “Yasmeen Rami”, ShipperCity = “Kuwait”, IsShipped = true} }; return OrderList; } } #endregion
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:
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()); }}
Step 10: 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); } }
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:
public void Configuration(IAppBuilder app) { HttpConfiguration config = new HttpConfiguration(); ConfigureOAuth(app); WebApiConfig.Register(config); app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); app.UseWebApi(config); }
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.