Token Based Authentication using Web API 2, Owin, and Identity

In this article, we will learn how to implement Token Based Authentication in Web API to secure the server resources using OAuth.

In this article, we will learn how to implement Token Based Authentication in Web API to secure the server resources using OAuth.
 

Introduction

 
In this article, we will learn how to implement Token Based Authentication in Web API to secure the server resources. 
 
There are 3 Common Methods of Web API Authentication:
  1. HTTP Basic Authentication
  2. API Keys
  3. OAuth
Here I am using OAuth authentication. OAuth is not technically an authentication method, but a method of both authentication and authorization. By using OAuth we can create Token Based Authentication API. First, what is Token Based Authentication in Web API, advantages of Token Based Authentication in Web API and how does it work?
 

What is Token Based Authentication in Web API?

 
Token-based authentication is a process where the user sends his credential to the server; server will validate the user details and generate a token which is sent as response to the users with each and every request.  This token is then used to access protected pages or resources instead of the login credentials for a designated period of time. This is called the Token Based Authentication approach.
 
Advantages of Token Based Authentication
  • Scalabilityof Servers
  • LooselyCoupling
  • MobileFriendly

How Does Token Based Authentication work?

 
When a user enters the name and password into the browser or mobile devices it sends these credentials (username and password) to the Authorization Server. Then the Authorization Server authenticates the username and password and then it generates an access token and returns it as a response to the user. This Access Token contains the identity of a user and also contains the token expiry time. Then the client application includes the Access Token in the Authorization header of the HTTP request to access the restricted resources from the Server until the token is expired.
 
Creating the Application.
 
Here I am using Visual Studio 2019 and .NetFrameWork 4.7 and Sql Server 2012 to create the example.

Step 1: Creating the Database.

First, we create a table to store user info.
 
Open SQL Server to create a database with any suitable name and then, create the table.
 
Here, I am using "OauthApi" as the database name and "ApiUsers" as the table name.
 
Tables Structure
  1. CREATE DATABASE OauthApi  
  2. GO  
  3. USE [OauthApi]  
  4.   
  5. CREATE TABLE [dbo].[ApiUsers](  
  6.     [UserId] [int] IDENTITY(1,1) NOT NULL,  
  7.     [UserName] [nvarchar](20) NULL,  
  8.     [UserPasswd] [nvarchar](50) NULL,  
  9.     [UserRole] [nvarchar](50) NULL,  
  10.  CONSTRAINT [PK_ApiUsers] PRIMARY KEY CLUSTERED   
  11. (  
  12.     [UserId] ASC  
  13. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ONON [PRIMARY]  
  14. ON [PRIMARY]  
  15. GO  
  16.   
  17. INSERT INTO ApiUsers VALUES(1, 'Amit''123456''SuperAdmin')  
  18. INSERT INTO ApiUsers VALUES(2, 'Subash''abc123''User')  
  19. INSERT INTO ApiUsers VALUES(3, 'Alok''123abc123''Admin')  
  20. GO 
Step 2.1: Creating the Project
 
Open Visual Studio, and click on "Create a new project".
 
 
Select ASP.NET web application from templates and click on "Next".
 
 
Then, give the project name as "OauthApp" and then click "Create".
 
 
 
Now, choose Web API from the template and click on "Create".
 
Now the application is created.
 
Step 2.2: Add references from NuGet packages to the application
 
After creating the application we have to add the following references from NuGet packages to the application.
  1. Microsoft.Owin.Host.SystemWeb
  2. Microsoft.Owin.Security.OAuth
  3. Microsoft.Owin.Cors
  4. Microsoft.AspNet.Identity.Owin
Step 2.3: Creating the ADO.NET Entity Data Model
 
To add ADO.NET Entity Data Model right click on the "Models" folder then goto "Add" then click on "New Item" and it will show "Add New Item" dialog box. From left pannel choose "Data" and then from right pannel choose "ADO.NET Entity Data Model", named as "DataContext" and click on "Add".
 
 
It will open "Entity Data Model Wizard" dialog box. Choose "EF Designer from database" and click on "Next".
 
 
It will open data connection wizard dialog box. Here, create a new data connection string for data access from the database to the application. Next click on "New Connection".
 
 
It will open connection properties dialog box. Here, we can see ASO.NET data model provides two types of connection and we can use it as per our requirement. Here, I am using "SQL Server Authentication" connection properties and selecting database name and test connection. If it succeeds then press the "OK" button.
 
 
Now, we can see the created connection string in the below image. Here, check the checkbox for the created connection string and save into the application's web.config file. Then, press Next.
 
 
It will open one more dialog box for Database Object and Setting. Here we can see the created database object list. Here, we can select the data table from all available tables and giving the Model Namespace as "DataContextModel" and click on Finish.
 
 
Now, you can see created "DataContext.edmx" in "Models" folder. In this created model, you can see the Model class and diagram as shown in below image.
 
 
Step 2.4: Add "Startup" Class and add support for OAuth Bearer Tokens Generation
 
Right click on your project then add new class named "Startup". To do so, go to the Solution Explorer > Right Click on Project Name form the Solution Explorer > Add > New Item > Select class > Enter the class name as Startup.cs > and then click on the Add button and it will contain the code below:
  1. using Microsoft.Owin;  
  2. using Microsoft.Owin.Cors;  
  3. using Microsoft.Owin.Security.OAuth;  
  4. using OauthApi.Provider;  
  5. using Owin;  
  6. using System;  
  7. using System.Web.Http;  
  8.   
  9. namespace OauthApi  
  10. {  
  11.     public class Startup  
  12.     {  
  13.         public void Configuration(IAppBuilder app)  
  14.         {  
  15.             ConfigureAuth(app);  
  16.             GlobalConfiguration.Configure(WebApiConfig.Register);  
  17.         }  
  18.   
  19.         public void ConfigureAuth(IAppBuilder app)  
  20.         {  
  21.             //this is very important line cross orgin source(CORS)it is used to enable cross-site HTTP requests  
  22.             //For security reasons, browsers restrict cross-origin HTTP requests  
  23.             app.UseCors(CorsOptions.AllowAll);    
  24.                
  25.             var OAuthOptions = new OAuthAuthorizationServerOptions  
  26.             {  
  27.                 AllowInsecureHttp = true,  
  28.                 TokenEndpointPath = new PathString("/token"),  
  29.                 AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),//token expiration time  
  30.                 Provider = new OauthProvider()  
  31.             };  
  32.   
  33.             app.UseOAuthBearerTokens(OAuthOptions);  
  34.             app.UseOAuthAuthorizationServer(OAuthOptions);  
  35.             app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());  
  36.   
  37.             HttpConfiguration config = new HttpConfiguration();  
  38.             WebApiConfig.Register(config);//register the request  
  39.         }  
  40.     }  

Here we created a new instance of the "OAuthAuthorizationServerOptions" class and then set the path for generating the tokens will be as "http://localhost:port/token". We have specified the expiry time for the access token as 30 minutes. We have also specified the implementation on how to validate the client credentials for users asking for the access tokens in the custom class named "OauthProvider". Then we passed the options to the extension method "UseOAuthAuthorizationServer" which will add the authentication middleware to the pipeline.
 
No need to use Global.asax class and fire up the Application_Start event after we’ve configured our "Startup" class so feel free to delete it.
 
Step 2.5: Implement the "OauthProvider" class
 
Add new folder named "Providers" to the project then add new class named "OauthProvider", paste the below code snippet to it.
  1. using Microsoft.Owin.Security.OAuth;  
  2. using OauthApi.Models;  
  3. using System;  
  4. using System.Linq;  
  5. using System.Security.Claims;  
  6. using System.Threading.Tasks;  
  7.   
  8. namespace OauthApi.Provider  
  9. {  
  10.     public class OauthProvider : OAuthAuthorizationServerProvider  
  11.     {  
  12.         public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)  
  13.         {  
  14.             await Task.Run(() => context.Validated());  
  15.         }  
  16.   
  17.         public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)  
  18.         {  
  19.             var identity = new ClaimsIdentity(context.Options.AuthenticationType);  
  20.   
  21.             using (var db = new DataContext())  
  22.             {  
  23.                 if (db != null)  
  24.                 {  
  25.                     var user = db.ApiUsers.Where(o => o.UserName == context.UserName && o.UserPasswd == context.Password).FirstOrDefault();  
  26.                     if (user != null)  
  27.                     {  
  28.                         identity.AddClaim(new Claim(ClaimTypes.Role, user.UserRole));  
  29.                         identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));  
  30.                         identity.AddClaim(new Claim("LoggedOn", DateTime.Now.ToString()));  
  31.                         await Task.Run(() => context.Validated(identity));  
  32.                     }  
  33.                     else  
  34.                     {  
  35.                         context.SetError("Wrong Crendtials""Provided username and password is incorrect");  
  36.                     }  
  37.                 }  
  38.                 else  
  39.                 {  
  40.                     context.SetError("Wrong Crendtials""Provided username and password is incorrect");  
  41.                 }  
  42.                 return;  
  43.             }  
  44.         }  
  45.     }  

In the above code the "OauthProvider" class inherits from class "OAuthAuthorizationServerProvider", we’ve overridden two methods "ValidateClientAuthentication" and "GrantResourceOwnerCredentials". The "ValidateClientAuthentication" method is responsible for validating the "Client" and the "GrantResourceOwnerCredentials" method is responsible to validate the username and password sent to the authorization server’s token endpoint.
 
Step 3: Modify Web API Controller
 
Now we will add an action method "GetValues" to "ValueController" so that we can check the Token-Based Authentication is working fine or not. To do that open the ValueController and add the below action method to it.
  1. //This method is For all types of role  
  2. [Authorize(Roles = "SuperAdmin, Admin, User")]  
  3. [HttpGet]  
  4. [Route("api/values/getvalues")]  
  5. public IHttpActionResult GetValues()  
  6. {  
  7.     var identity = (ClaimsIdentity)User.Identity;  
  8.     var roles = identity.Claims  
  9.                 .Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value);  
  10.     var LogTime = identity.Claims  
  11.                 .FirstOrDefault(c => c.Type == "LoggedOn").Value;  
  12.     return Ok("Hello: " + identity.Name + ", " +  
  13.         "Your Role(s) are: " + string.Join(",", roles.ToList()) +  
  14.         "Your Login time is :" + LogTime);  

Testing the Web API Application.

 
To test this first, you need to run your Web API application. Here I am using a client tool called Postman to test web API.
 
Step 4.1: Test without Access Token
 
Open the Postman application and provide the necessary details as given in the below image.
 
 
Here we will get 401 unauthorized responses.
 
Step 4.2: Create the Access Token
 
First we try to create Access Token with invalid credentials.
 
 
Here we will get status as 400 Bad Request and also get the error describing that the provided username and password are incorrect. Let’s generate the access token with valid credentials as shown in the below image.
 
 
Now we will get status code 200 Ok and access token value, token type as Bearer and the token expire time in seconds in the Response section.
 
Step 4.3: Test with Access Token
 
Copy the access token and use it as shown in the below image.
 
 
If all is correct we’ll receive HTTP status 200 along with the secured data in the response body.
 
In this article we will learn how to create Access Token and how to use it using Token Based Authentication. Hope this article will help the readers. Happy Coding!!!