Web API Token Based Authentication

Introduction

 
In this article, we will learn how to implement Token Based Authentication in Web APIs to secure the data.
 
There are 4 common methods of Web API Authentication:
  1. HTTP Authentication Schemes (Basic & Bearer)
  2. API Keys
  3. OAuth (2.0)
  4. OpenID Connect
Here we will learn OAuth authentication. OAuth is an open standard for token based authentication and authorization on internet. By using OAuth we can create Token Based Authentication API.
 

What is Token Based Authentication in Web API?

 
Token-based authentication is a process where the client application first sends a request to Authentication server with a valid credentials. The Authentication server sends an Access token to the client as a response. This token contains enough data to identify a particular user and it has an expiry time. The client application then uses the token to access the restricted resources in the next requests until the token is valid. If the Access token is expired, then the client application can request for a new access token by using Refresh token.
Advantages of Token Based Authentication
  • Scalability of Servers
  • Loosely Coupling
  • Mobile-Friendly
Let’s discuss the step by step procedure to create Token-Based Authentication,
 
Step 1 - Create ASP.NET Web Project in Visual Studio 2019 
 
We have to create web project in Visual Studio as given in the below image. Choose ASP.Net Web Application from the menu.
 
 
 
Give the project name as:WEBAPITOKENAUTHENTICATION.
 
 
Now choose the empty template and check the "MVC" and "Web API" on the right hand side.
 
 
Step 2 - Addition Of References
 
In this step,we have to add Nuget References like the below image,
 
 
 
Here we have to add the following references : 
  • Microsoft.Owin.Host.SystemWeb 
  • Microsoft.Owin.Security.OAuth
  • Microsoft.Owin.Cors
 
 
 
Step 3 - Create APIAUTHORIZATIONSERVERPROVIDER.cs Class File
 
Now, let's create the class file to provide credentials to access data depending on username, password, and roles. 
 
 
 
Code is given below:
  1. public class APIAUTHORIZATIONSERVERPROVIDER : OAuthAuthorizationServerProvider  
  2.     {  
  3.         public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)  
  4.         {  
  5.             context.Validated(); //   
  6.         }  
  7.         public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)  
  8.         {  
  9.             var identity = new ClaimsIdentity(context.Options.AuthenticationType);  
  10.             if (context.UserName == "admin" && context.Password == "admin")  
  11.             {  
  12.                 identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));  
  13.                 identity.AddClaim(new Claim("username""admin"));  
  14.                 identity.AddClaim(new Claim(ClaimTypes.Name, "Hi Admin"));  
  15.                 context.Validated(identity);  
  16.             }  
  17.             else if (context.UserName == "user" && context.Password == "user")  
  18.             {  
  19.                 identity.AddClaim(new Claim(ClaimTypes.Role, "user"));  
  20.                 identity.AddClaim(new Claim("username""user"));  
  21.                 identity.AddClaim(new Claim(ClaimTypes.Name, "Hi User"));  
  22.                 context.Validated(identity);  
  23.             }  
  24.             else  
  25.             {  
  26.                 context.SetError("invalid_grant""Provided username and password is incorrect");  
  27.                 return;  
  28.             }  
  29.         }  
  30.     }  
Step 4 - Create a AuthenticationStartup.cs Class File
 
Here, we need to create a new class file to implement the code configuration provider and create an instance of class APIAUTHORIZATIONSERVERPROVIDER.
 
 
 
Code is given below:
  1. public class AuthenticationStartup  
  2.    {  
  3.        public void Configuration(IAppBuilder app)  
  4.        {    
  5.            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);  
  6.            var myProvider = new APIAUTHORIZATIONSERVERPROVIDER();  
  7.            OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions  
  8.            {  
  9.                AllowInsecureHttp = true,  
  10.                TokenEndpointPath = new PathString("/token"),  
  11.                AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),  
  12.                Provider = myProvider  
  13.            };  
  14.            app.UseOAuthAuthorizationServer(options);  
  15.            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());  
  16.   
  17.   
  18.            HttpConfiguration config = new HttpConfiguration();  
  19.            WebApiConfig.Register(config);  
  20.        }  
  21.    }  
Step 5 - Create a APIAUTHORIZEATTRIBUTE.cs Class File
 
We need to create this class to handle unauthorized access to resources and show the proper message.
 
 
 
Code is given below:
  1. public class APIAUTHORIZEATTRIBUTE : System.Web.Http.AuthorizeAttribute  
  2.   {  
  3.       protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)  
  4.       {  
  5.           if (!HttpContext.Current.User.Identity.IsAuthenticated)  
  6.           {  
  7.               base.HandleUnauthorizedRequest(actionContext);  
  8.           }  
  9.           else  
  10.           {  
  11.               actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);  
  12.           }  
  13.       }  
  14.   }  
Step 6 - Create a controller with name UserController
 
Now we have to create an empty web api controller with name usercontroller. In this controller, we will write the actions with different authorization and roles.
 
 
The first action "Get" will be available for anonymous users .No authetication or token is needed for this.
  1. [AllowAnonymous]  
  2. [HttpGet]  
  3. [Route("api/data/forall")]  
  4. public IHttpActionResult Get()  
  5. {  
  6.     return Ok("Now server time is: " + DateTime.Now.ToString());  

The second action "GetForAuthenticate" only allows the authorized user to access it. 
  1. [Authorize]  
  2. [HttpGet]  
  3. [Route("api/data/authenticate")]  
  4. public IHttpActionResult GetForAuthenticate()  
  5. {  
  6.     var identity = (ClaimsIdentity)User.Identity;  
  7.     return Ok("Hello " + identity.Name);  
  8. }  
The third action "GetForAdmin"  checks authorization and allows only admins to access it.
  1. [Authorize(Roles = "admin")]  
  2. [HttpGet]  
  3. [Route("api/data/authorize")]  
  4. public IHttpActionResult GetForAdmin()  
  5. {  
  6.     var identity = (ClaimsIdentity)User.Identity;  
  7.     var roles = identity.Claims  
  8.                 .Where(c => c.Type == ClaimTypes.Role)  
  9.                 .Select(c => c.Value);  
  10.     return Ok("Hello " + identity.Name + " Role: " + string.Join(",", roles.ToList()));  
  11. }  
Step 7 - Accessing the controller using Postman 
 
Now we have to access the controller. For that purpose, we are using postman to get data.I n case ofthe  first action "Get",we can access the data without generating a token as no authorization is needed for it, by just sending GET request for route "api/data/forall".
 
 
But for the rest of the actions, we have to generate a token using credentials. So we have to do post request for the token.
 
 
Now once the token is generated for the "user" now we can easily access the actions by using the user token.
 
 
Similarly, we can access the action as "admin" by generating token as admin and then using it.
 
 
In the same way, the other actions can be accessed by user or admin depending on the way the token is generated.