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 it at the controller level, it will apply for all APIs in that controller, or you can use it 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:

New project

Enter "Solution name" and click OK. Next dialogue opens up, which looks like the following.

Solution name

Select ASP. Core Version from the above drop-down and next select the application type. Click Ok.

The project structure looks like this.

Project structure

We have the code base ready, we need to implement the wrapper class to handle the API request.

Step 2. Create Custom Authorization Class and Override.

Right-click on the solution and add a new class. Enter the class name and click on Add.

Create Custom Authorization

Next Inherite Attribute, IAuthorizationFilter to CustomAuthorization class which has overridden the OnAuthorization method.

[AttributeUsage(AttributeTargets.Class)]
public class CustomAuthorization : Attribute, IAuthorizationFilter
{    
    /// <summary>
    /// This will Authorize User
    /// </summary>
    /// <returns></returns>
    public void OnAuthorization(AuthorizationFilterContext filterContext)
    {
        
    }
}

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.

Microsoft.Extensions.Primitives.StringValues authTokens;
filterContext.HttpContext.Request.Headers.TryGetValue("authToken", out authTokens);
var _token = authTokens.FirstOrDefault();

Later, once you get the token value, you can validate, and based on that you can return the corresponding response with the 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.

[AttributeUsage(AttributeTargets.Class)]
public class CustomAuthorization : Attribute, IAuthorizationFilter
{


    /// <summary>
    /// This will Authorize User
    /// </summary>
    /// <returns></returns>
    public void OnAuthorization(AuthorizationFilterContext filterContext)
    {
        
        if (filterContext != null)
        {
            Microsoft.Extensions.Primitives.StringValues authTokens;
            filterContext.HttpContext.Request.Headers.TryGetValue("authToken", out authTokens);

            var _token = authTokens.FirstOrDefault();

            if (_token != null)
            {    
                string authToken = _token;
                if (authToken != null)
                {
                    if (IsValidToken(authToken))
                    {
                        filterContext.HttpContext.Response.Headers.Add("authToken", authToken);
                        filterContext.HttpContext.Response.Headers.Add("AuthStatus", "Authorized");

                        filterContext.HttpContext.Response.Headers.Add("storeAccessiblity", "Authorized");
      
                        return;
                    }
                    else
                    {
                        filterContext.HttpContext.Response.Headers.Add("authToken", authToken);
                        filterContext.HttpContext.Response.Headers.Add("AuthStatus", "NotAuthorized");    
                        
                        filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                        filterContext.HttpContext.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "Not Authorized";
                        filterContext.Result = new JsonResult("NotAuthorized")
                        {
                            Value = new 
                            {
                                Status = "Error",
                                Message = "Invalid Token"
                            },
                        };
                    }

                }

            }
            else
            {
                filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.ExpectationFailed;
                filterContext.HttpContext.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "Please Provide authToken";
                filterContext.Result = new JsonResult("Please Provide authToken")
                {
                    Value = new
                    {
                        Status = "Error",
                        Message = "Please Provide authToken"
                    },
                };
            }
        }
    }

    public bool IsValidToken(string authToken)
    {
        //validate Token here
        return true;
    }
}

Step 3. How to use the CustomAuthorization class.

We can use this class for each API or for each controller like in the following.

API

Step 4. Execute and Test.

I'll try executing it with a token and without a token.

Without authToken

AuthToken

With authToken

Environment

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!


Similar Articles