How To Override Attribute Class To Do Custom Authorization In .NET Core

Introduction

 
In .NET CORE, you might come across a situation in which you must implement your own authorization or want to send key values in each API request. In such cases, you can't implement authentication techniques in each API and you can't write code to retrieve key values in each API. We need a common wrapper class to retrieve values from all the request headers. We have to override the Attribute class to achieve this. 
 
In this article, I'm going to explain how to create your own AuthorizationClass and retrieve the values. Also, I will create a wrapper class to use as an annotation of each controller or for each API. (i.e. you can use at the controller level, it will apply for all APIs in that controller, or you can use for each API independently. 
 
Step 1 - Create a New API Project in VS
 
Follow the below steps to create a new .NET Core Web API project in your Visual Studio 2017.
 
Go to file > click on New > Select New Project. A new project dialogue opens up, which looks like the following:
 
How To Override Attribute Class To Do Custom Authorization In .NET Core
 
Enter "Solution name" and click OK. Next dialogue opens up, which looks like the following:
 
How To Override Attribute Class To Do Custom Authorization In .NET Core
 
Select ASP. Core Version from the above drop-down and next select the application type. Click Ok.
 
The project structure looks like this:
 
How To Override Attribute Class To Do Custom Authorization In .NET Core
 
We have code base ready, we need to implement the wrapper class to handle the API request. 
 
Step 2 - Create CustomAuthorization Class and Override
 
Right-click on the solution and add a new class. Enter the class name and click on Add.
 
How To Override Attribute Class To Do Custom Authorization In .NET Core
 
Next Inherite Attribute, IAuthorizationFilter to CustomAuthorization class which has overridden the OnAuthorization method. 
  1. [AttributeUsage(AttributeTargets.Class)]  
  2.    public class CustomAuthorization : Attribute, IAuthorizationFilter  
  3.    {    
  4.        /// <summary>  
  5.        /// This will Authorize User  
  6.        /// </summary>  
  7.        /// <returns></returns>  
  8.        public void OnAuthorization(AuthorizationFilterContext filterContext)  
  9.        {  
  10.             
  11.        }  
  12.   }  
The OnAuthorization Method has the AuthorizationFilterContext parameter. From AuthorizationFilterContext, we can read the header values. We can retrieve the value by its key name. 
 
In our example the key name is "authToken", we need to specify the same name in the API request header. 
  1.   Microsoft.Extensions.Primitives.StringValues authTokens;  
  2.                filterContext.HttpContext.Request.Headers.TryGetValue("authToken", out authTokens);  
  3. var _token = authTokens.FirstOrDefault();  
Later, once you got token value, you can validate and based on that you can return the corresponding response with status code.
 
We can set up the status code and our own message for the valid and invalid requests.
 
The overall custom class looks like the following:
  1. [AttributeUsage(AttributeTargets.Class)]  
  2.     public class CustomAuthorization : Attribute, IAuthorizationFilter  
  3.     {  
  4.   
  5.   
  6.         /// <summary>  
  7.         /// This will Authorize User  
  8.         /// </summary>  
  9.         /// <returns></returns>  
  10.         public void OnAuthorization(AuthorizationFilterContext filterContext)  
  11.         {  
  12.              
  13.             if (filterContext != null)  
  14.             {  
  15.                 Microsoft.Extensions.Primitives.StringValues authTokens;  
  16.                 filterContext.HttpContext.Request.Headers.TryGetValue("authToken", out authTokens);  
  17.   
  18.                 var _token = authTokens.FirstOrDefault();  
  19.   
  20.                 if (_token != null)  
  21.                 {    
  22.                     string authToken = _token;  
  23.                     if (authToken != null)  
  24.                     {  
  25.                         if (IsValidToken(authToken))  
  26.                         {  
  27.                             filterContext.HttpContext.Response.Headers.Add("authToken", authToken);  
  28.                             filterContext.HttpContext.Response.Headers.Add("AuthStatus""Authorized");  
  29.   
  30.                             filterContext.HttpContext.Response.Headers.Add("storeAccessiblity""Authorized");  
  31.       
  32.                             return;  
  33.                         }  
  34.                         else  
  35.                         {  
  36.                             filterContext.HttpContext.Response.Headers.Add("authToken", authToken);  
  37.                             filterContext.HttpContext.Response.Headers.Add("AuthStatus""NotAuthorized");              
  38.   
  39.                             filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;  
  40.                             filterContext.HttpContext.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "Not Authorized";  
  41.                             filterContext.Result = new JsonResult("NotAuthorized")  
  42.                             {  
  43.                                 Value = new  
  44.                                 {  
  45.                                     Status = "Error",  
  46.                                     Message = "Invalid Token"  
  47.                                 },  
  48.                             };  
  49.                         }  
  50.   
  51.                     }  
  52.   
  53.                 }  
  54.                 else  
  55.                 {  
  56.                     filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.ExpectationFailed;  
  57.                     filterContext.HttpContext.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "Please Provide authToken";  
  58.                     filterContext.Result = new JsonResult("Please Provide authToken")  
  59.                     {  
  60.                         Value = new  
  61.                         {  
  62.                             Status = "Error",  
  63.                             Message = "Please Provide authToken"  
  64.                         },  
  65.                     };  
  66.                 }  
  67.             }  
  68.         }  
  69.   
  70.         public bool IsValidToken(string authToken)  
  71.         {  
  72.             //validate Token here  
  73.             return true;  
  74.         }  
  75.     }  
Step 3 - How to use CustomAuthorization class
 
We can use this class for each API or for each controller like in the following:
 
How To Override Attribute Class To Do Custom Authorization In .NET Core
 
Step 4 - Execute and Test
 
I'll try executing it with a token and without a token.
 
Without authToken:
 
How To Override Attribute Class To Do Custom Authorization In .NET Core
 
With authToken:
 
How To Override Attribute Class To Do Custom Authorization In .NET Core
 
It's working.
 

Summary

 
In this article, we discussed how to override an Attribute class and do custom validation. Also, we saw how to retrieve a key value from the headers from each request of API in .NET CORE. The sample code is also attached. Hope it's helpful!