Authorization Filters in ASP.NET Core MVC

Authorization Filter in ASP.NET Core MVC

In this article, I will discuss the Authorization Filter in ASP.NET Core MVC Application with Examples. Please read our previous article discussing Response Caching in ASP.NET Core Applications. As part of this article, we will discuss the following pointers in detail.

  1. What is the Authorization Filter in ASP.NET Core MVC?
  2. What is Authentication?
  3. What is Authorization?
  4. Examples to Understand Authorization Filter in ASP.NET Core MVC
  5. Custom Authorization Filter in ASP.NET Core MVC
  6. When Should We Use Authorization Filter in ASP.NET Core MVC?
What is the Authorization Filter in ASP.NET Core MVC?

In ASP.NET Core MVC, the Authorization Filter allows us to apply authorization rules to controllers and actions within our application. Authorization Filters in ASP.NET Core are responsible for checking whether a user is allowed to perform an action or access a resource. These filters run before the action method is executed, ensuring the user has permission to access the method.

Authorization filters are executed after the routing but before model binding and other action filters. If the authorization fails (e.g., the user does not have the required permissions), the filter short-circuits the request, and the action method does not execute.

What is Authentication?

Authentication is a process that ensures and confirms a user’s identity. In other words, we can say that it is a process to validate someone against some data source. Let us understand Authentication from a layman’s point of view. For this, please have a look at the following diagram.

What is Authentication?

The above image shows the different sections of an IT Company, such as Reception, HR Section, Accounts Section, Server Room, etc. At the gate, we have biometrics to verify the employee. Suppose one employee comes. This biometrics checks the employee credentials against some data source, and if it is found that the employee is valid, it only allows entering into the campus. This is nothing but Authentication.

What is Authorization?

Authorization is a mechanism that determines whether users can access a particular resource. The most important point that you need to remember is that authentication happens first and then only authorization. For a better understanding, please have a look at the following image.

What is Authorization?

As shown in the above image, once the employee is authenticated, he enters the Campus. Then, Authorization comes into the picture. Within the campus, which section he is allowed to enter is determined by the Authorization process. The Role of the Employee does this. If the Employee has list privileges, he may not allow each section. On the other hand, if the Employee has the highest privileges, he may be allowed to enter each section.

Types of Authorization Filters in ASP.NET Core MVC:

By default, in the ASP.NET Core MVC applications, all the action methods of all controllers can be accessed by both authenticated and anonymous users. However, if you want the action methods to be available only for authenticated and authorized users, you need to use the Authorization Filter in ASP.NET Core MVC. ASP.NET Core provides two built-in attributes, [Authorize] and [AllowAnonymous], that can be used as filters.

  • Authorize Attribute: The [Authorize] Attribute specifies that only authenticated users or users with certain roles or policies can access a particular action method or controller. The [Authorize] attribute specifies that the associated action method or controller requires the user to be authenticated. 
  • AllowAnonymous Attribute: The [AllowAnonymous] attribute specifies that an action method or controller should allow anonymous access, even when an [Authorize] attribute is applied at the controller or action level. In other words, it permits unauthenticated users to access the decorated resource, bypassing any authentication and authorization checks that might be in place at higher levels.
Examples to Understand Authorization Filter in ASP.NET Core MVC:

Let us understand the Authorize and AllowAnonymous Filters with an example. First, create a new ASP.NET Core Application using the Model-View-Controller Project Template. Once you create the Project, then modify the Home Controller as follows. As you can see, we created the HomeController with three action methods, i.e., NonSecureMethod, SecureMethod, and Login. We want the SecureMethod to be accessed by authenticated users while the NonSecureMethod and Login methods to be accessed by anyone. Whenever an unauthenticated user wants to access the SecureMethod, we must redirect that user to the Login action method.

using Microsoft.AspNetCore.Mvc;
namespace FiltersDemo.Controllers
{
    public class HomeController : Controller
    {
        public string NonSecureMethod()
        {
            return "This method can be accessed by everyone as it is non-secure method";
        }

        public string SecureMethod()
        {
            return "This method needs to be access by authorized users as it SecureMethod";
        }

        public string Login()
        {
            return "This is the Login Page";
        }
    }
}

At this point, authenticated and anonymous users can access the SecureMethod and the NonSecureMethod methods using the following two URLs.
/Home/SecureMethod
/Home/NonSecureMethod

If you want the Secure Method to be accessed only by authenticated and authorized users, then you need to decorate this method with the Authorize attribute, as shown below.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace FiltersDemo.Controllers
{
    public class HomeController : Controller
    {
        public string NonSecureMethod()
        {
            return "This method can be accessed by everyone as it is non-secure method";
        }

        [Authorize] //Requires authentication for the SecureMethod 
        public string SecureMethod()
        {
            return "This method needs to be access by authorized users as it SecureMethod";
        }

        public string Login()
        {
            return "This is the Login Page";
        }
    }
}

Now run the application and navigate to /Home/SecureMethod. You will see the following Internal Server Error.

Examples to Understand Authorization Filter in ASP.NET Core MVC

Instead of displaying the above error page, we need to redirect the user to the Login Page. In the later part of this article, I will show you how to create Custom Authentication Filters to achieve the same in ASP.NET Core MVC Applications.

Can we apply the Authorize Attribute at the controller level?

Applying the Authorize attribute at the controller level applies to all the action methods present within that controller. For a better understanding, please modify the Home Controller as follows. The Home Controller Action methods are now protected with the Authorize Attribute. So, only the authenticated users can now access the SecureMethod(), NonSecureMethod(), and Login action methods.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace FiltersDemo.Controllers
{
    [Authorize] //Requires authentication for the entire controller 
    public class HomeController : Controller
    {
        public string NonSecureMethod()
        {
            return "This method can be accessed by everyone as it is non-secure method";
        }

        public string SecureMethod()
        {
            return "This method needs to be access by authorized users as it SecureMethod";
        }

        public string Login()
        {
            return "This is the Login Page";
        }
    }
}

Now, suppose you want to allow anonymous access to the NonSecureMethod and Login method of the Home Controller. In that case, you need to decorate the NonSecureMethod and Login method with the AllowAnonymous attribute, as shown below. The AllowAnonymous attribute in ASP.NET Core MVC is used to skip the authorization enforced by the Authorization Filter.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace FiltersDemo.Controllers
{
    [Authorize] //Requires authentication for the entire controller 
    public class HomeController : Controller
    {
        public string SecureMethod()
        {
            return "This method needs to be access by authorized users as it SecureMethod";
        }

        [AllowAnonymous]
        public string NonSecureMethod()
        {
            return "This method can be accessed by everyone as it is non-secure method";
        }

        [AllowAnonymous]
        public string Login()
        {
            return "This is the Login Page";
        }
    }
}

Note: If both Authorize and AllowAnonymous Attributes are applied to an action method, then the AllowAnonymous attribute will take priority and be accessed by any user.

Custom Authorization Filter in ASP.NET Core:

We can also create Custom Authentication filters. To create Custom Authentication in ASP.NET Core MVC, we need to create a class implementing the IAuthorizationFilter or IAsyncAuthorizationFilter interface and provide implementations for the OnAuthorization method, where you need to write the custom authentication logic as per our business requirements. 

Example to Understand Custom Authorization Filter in ASP.NET Core

In ASP.NET Core, we can create a Custom Authorization Filter to redirect the User to the login page when the user is not authenticated. Let us see how we can create a custom authorization filter to achieve this:

Create a class file named CustomAuthorizationFilterAttribute.cs, and then copy and paste the following code. As you can see, the following class is inherited from the Attribute and IAuthorizationFilter classes so that we can use this class as an Attribute. This class implements the IAuthorizationFilter interface and provides the implementation for the OnAuthorization method, where we have written our custom authorization logic.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Security.Claims;

namespace FiltersDemo.Models
{
    public class CustomAuthorizationFilterAttribute : Attribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            // Your custom authorization logic here
            if (!IsAuthorized(context.HttpContext.User))
            {
                // If not authenticated, redirect to the login page
                context.Result = new RedirectToRouteResult(new RouteValueDictionary
                {
                    { "controller", "Home" },   // Change "Home" to your login controller name
                    { "action", "Login" }       // Change "Login" to your login action method name
                });
            }
        }

        private bool IsAuthorized(ClaimsPrincipal user)
        {
            // Check if the user is authenticated
            // Implement your custom authorization logic here
            // Check roles, claims, policies, or any other criteria
            // Return true if authorized, false if not

            return false; // For demonstration purposes
        }
    }
}

Now, we need to decorate the controller or action method where we need to implement our custom authorization logic. Let us decorate the SecureMethod with our Custom Authorization Filter Attribute. So, modify the Home Controller as follows:

using FiltersDemo.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace FiltersDemo.Controllers
{
    public class HomeController : Controller
    {
        [CustomAuthorizationFilterAttribute] // Apply the custom CustomAuthorizationFilterAttribute 
        public string SecureMethod()
        {
            return "This method needs to be access by authorized users as it SecureMethod";
        }

        [AllowAnonymous]
        public string NonSecureMethod()
        {
            return "This method can be accessed by everyone as it is non-secure method";
        }

        [AllowAnonymous]
        public string Login()
        {
            return "This is the Login Page";
        }
    }
}

With the above changes in place, visit the SecureMethod, and you will see that it will redirect to the Login Page.

Creating a Custom Authorization Filter

In the previous example, the CustomAuthorizationFilterAttribute class is inherited from the Attribute class, and that’s why we apply the CustomAuthorizationFilterAttribute directly to the action methods and controller. Let us remove the inherited Attribute class from the CustomAuthorizationFilterAttribute class definition, and let’s inherit from the IAuthorizationFilter interface. So, modify the CustomAuthorizationFilterAttribute class as follows:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Security.Claims;

namespace FiltersDemo.Models
{
    public class CustomAuthorizationFilter : IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            // Your custom authorization logic here
            if (!IsAuthorized(context.HttpContext.User))
            {
                // If not authenticated, redirect to the login page
                context.Result = new RedirectToRouteResult(new RouteValueDictionary
                {
                    { "controller", "Home" },   // Change "Account" to your login controller name
                    { "action", "Login" }       // Change "Login" to your login action method name
                });
            }
        }

        private bool IsAuthorized(ClaimsPrincipal user)
        {
            // Check if the user is authenticated
            // Implement your custom authorization logic here
            // Check roles, claims, policies, or any other criteria
            // Return true if authorized, false if not

            return false; // For demonstration purposes
        }
    }
}
Register the Filter Globally, on a Controller, or an Action:

Now, we can register the Custom Authorization Filter at 3 different places. We can register the filter globally, which means it will be applied to all controllers and actions in your application. To do so, you need to modify the MVC Service registration in your Program.cs class file as follows.

builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add(new CustomAuthorizationFilter());
});
Using Authentication Filter at Controller and Action Method Level:

You can also apply the Custom Authorization Filter to a specific controller or action method using the built-in ServiceFilter and TypeFilter Attribute. We use the TypeFilter attribute in the code below to specify the CustomAuthorizationFilter.

using FiltersDemo.Models;
using Microsoft.AspNetCore.Mvc;

namespace FiltersDemo.Controllers
{
    public class HomeController : Controller
    {
        [TypeFilter(typeof(CustomAuthorizationFilter))]
        public string Index()
        {
            return "String Data from Index Action Method";
        }
    }
}
Custom Asynchronous Authorization Filter in ASP.NET Core MVC

It is also possible to create the Custom Authorization Filter asynchronous. For this, our Custom Authorization Filter class needs to implement the IAsyncAuthorizationFilter interface and provide the implementation for the OnAuthorizationAsync method. This type of filter is suitable for performing asynchronous operations, such as database calls or any I/O-bound work, within your authorization logic.

Create the Custom Asynchronous Authorization Filter:

So, create a class file named CustomAsyncAuthorizationFilter.cs and copy and paste the following code. Here, you can see the CustomAsyncAuthorizationFilter class implement the IAsyncAuthorizationFilter interface and provide implementations for the OnAuthorizationAsync method where we have written the custom Authorization Logic:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace FiltersDemo.Models
{
    public class CustomAsyncAuthorizationFilter : IAsyncAuthorizationFilter
    {
        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            // Your asynchronous custom authorization logic here
            bool isAuthorized = await CheckUserAuthorizationAsync(context);

            if (!isAuthorized)
            {
                // If not authenticated, redirect to the login page
                context.Result = new RedirectToRouteResult(new RouteValueDictionary
                {
                    { "controller", "Home" },   // Change "Account" to your login controller name
                    { "action", "Login" }       // Change "Login" to your login action method name
                });
            }
        }

        private async Task<bool> CheckUserAuthorizationAsync(AuthorizationFilterContext context)
        {
            // Implement your asynchronous authorization logic here
            // For example, you can check user permissions, roles, etc., using async calls
            await Task.Delay(1000); // Simulate async work, like a database call

            // Return true if authorized, false otherwise
            return false;
        }
    }
}
Register the Filter:

You can register the filter globally or on specific controllers or actions:

Globally:
builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add(new CustomAsyncAuthorizationFilter());
});
On a Controller or Action:
using FiltersDemo.Models;
using Microsoft.AspNetCore.Mvc;

namespace FiltersDemo.Controllers
{
    [TypeFilter(typeof(CustomAsyncAuthorizationFilter))]
    public class SomeController : Controller
    {
        // All actions in this controller will use the CustomAsyncAuthorizationFilter
    }

    public class AnotherController : Controller
    {
        [TypeFilter(typeof(CustomAsyncAuthorizationFilter))]
        public async Task<IActionResult> SomeAction()
        {
            // This action will use the CustomAsyncAuthorizationFilter
            return View();
        }
    }
}

Note: Once we discuss the ASP.NET Core Identity, you will see the real implementation with proper roles, claims, etc.

When Should We Use Authorization Filter in ASP.NET Core MVC?

Authorization filters in ASP.NET Core MVC should be used when you need to control access to specific controllers or actions within your web application based on authentication and authorization rules. The following are some common scenarios in which you should use authorization filters:

  • Securing Sensitive Data or Functionality: Use authorization filters to protect endpoints that access sensitive data or perform sensitive operations, ensuring that only authorized users can access them.
  • Role-Based Access Control: When you have different user roles in your application (like admin, user, and moderator) and want to restrict access to certain actions or controllers based on these roles.
  • Error Handling: Authorization filters can also handle unauthorized access by redirecting users to login pages, displaying access-denied messages, or taking other appropriate actions.

In the next article, I will discuss Action Filters in ASP.NET Core MVC Application. In this article, I try to explain the Authorization Filter in ASP.NET Core MVC Application with Examples. I hope you understand the need for and use of Authorization Filters in ASP.NET Core MVC Applications.

Leave a Reply

Your email address will not be published. Required fields are marked *