Creating a Custom Authorize Attribute in C#

I wanted to share something that I wrote from a large project I completed earlier in 2020. 
If you have need of adding a security authorization to a C# project, normally you will turn to use the built-in security attributes. This is done by using the references found below.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

This allows your code to use the default [Authorize] attribute above your classes, controllers, methods, views, and so on. 

In my example, the tool I was creating was named the “Delegation of Authority” tool, or “DoA” for short, so you will see that name pop up in the naming of the classes. 

Create the Custom AuthorizeAttribute Class

In this project, I needed to create a custom class with the authorize attribute to authorize people. To accomplish this, we implement the AuthorizeAttribute in a new class as seen below:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class DoAAuthorizationHandler : AuthorizeAttribute

Add Ability to Pass Custom Security Roles

The purpose of the authorization class was to give specific roles to people based on a list of users in a SQL database table. I already had custom security roles built as Enums, but I needed to make it so the custom authorize class would take them as a parameter. So we add it to the constructor and we overwrite the built-in “Roles” variable.

public DoAAuthorizationHandler(params SecurityRole[] roles)
{
  Roles = string.Join(",", roles);
}

By joining the roles, we are given the ability to make classes or methods that allow multiple security roles to pass users through. This is seen more in-depth on this Microsoft page on custom C# authorize attributes, we just happen to overwrite that functionality with this constructor.

For now, though, we will just pass a single admin role to the controller.

[DoAAuthorizationHandler(SecurityRole.admin)]
public class AdminController : Controller

Override AuthorizeCore and Add In Your Own Code

Now we have a working custom authorize class that takes in a custom enum for the security roles, but we aren’t checking anything yet so let’s get started on that.

The next step is to override the built-in process for checking if the person is authorized. This is called AuthorizeCore as seen below. 

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
}

At this point, the rest of the function is mostly straight forward. We are going to check the role passed to the class and figure out if the current user trying to access the page has the correct role to be authorized.

Below I instantiate the class we use to grab who the user is. Each user has a distinct ID (I call it MDID here) and that ID is used as the key. From there I check their role in our database and return the proper boolean for if they are authorized or not.

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
  bool isAuthorized = false;
  SecurityService securityService = new SecurityService(webRepository, webServiceAccount);
  IPrincipal principal = new HttpContextPrinciple();
 
  webUser = new User(securityService, principal);
  int MDID = webUser.iMDID;
 
  try
  {
     isAuthorized = securityService.CheckUserAuthorizationForDoATool(MDID, Roles);
  }
  catch (Exception)
  {
      throw;
  }

  return isAuthorized;
}

Create a Custom Redirect for Unauthorized Requests

We now have a working custom authorize class that checks based on a user’s security role. If a user without the correct role tries to go to the admin page, they will be denied. But what does the deny page look like? Right now it will show the user an HTTP 403-forbidden page. Maybe we don’t want that and would rather show our own custom “Not Authorized” page. So here we go to override the method that takes us to the 403 page. 

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            filterContext.Result = new RedirectToRouteResult(
            new RouteValueDictionary{
                {"controller", "Default" },
                {"action", "NotAuthorized" }
            });
        }

In this example, I take the user to a custom page and show them a nicer error that explains why they might have received the error. 

Final Code for Custom Authorize Attribute Function

Finally, we have all the code put together and create a nice function to verify users when they attempt to access specific pages.

That wraps up the basics for creating a custom authorization handler. Thank you for reading and I hope that helps explain how to make a custom c# authorize attribute class.