In ASP.NET Core MVC, Authorization Filters help enforce security by determining whether a user is authorized to access a specific controller or action. Sometimes, authorization decisions require asynchronous operations—for example, retrieving user roles from a database. For such scenarios, Async Authorization Filters are used.

The IAsyncAuthorizationFilter interface allows you to implement asynchronous logic in your custom authorization filters, making it ideal for performing database lookups or calling external services before allowing access.

What We’ll Build

In this article, we’ll create:

  • A custom asynchronous authorization filter named CustomAsyncAuthorizationFilter
  • The filter will:
    • Read the UserId from the session
    • Use that UserId to fetch the user’s role from the database
    • Check whether the user has the “Admin” role
    • Redirect unauthorized users to an error page

Let’s Get Started

Code Snippet of CustomAsyncAuthorizationFilter

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;
using WebApplication4.Models;

namespace WebApplication4.Filters
{
    public class CustomAsyncAuthorizationFilter : Attribute, IAsyncAuthorizationFilter
    {
        public readonly DatabaseContext _dbcontext;
        public CustomAsyncAuthorizationFilter(DatabaseContext dbcontext)
        {
            _dbcontext = dbcontext;
        }

        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            int? currentUserId = context.HttpContext.Session.GetInt32("UserId");

            var getroleName = await (from userrole in _dbcontext.UserRoles
                                     where userrole.UserId == currentUserId
                                     select userrole.Name).SingleOrDefaultAsync();


            // Use 'await' to get data from the database 

            if (!string.IsNullOrEmpty(getroleName))
            {
                if (getroleName != "Admin")
                {
                    context.Result = new RedirectToRouteResult
                (
                new RouteValueDictionary(new
                {
                    action = "Error",
                    controller = "Error"
                }));
                    return;
                }
                else
                {
                    context.Result = new RedirectToRouteResult
               (
               new RouteValueDictionary(new
               {
                   action = "Error",
                   controller = "Error"
               }));
                    return;
                }
            }
            else
            {
                context.Result = new RedirectToRouteResult
                (
                new RouteValueDictionary(new
                {
                    action = "Error",
                    controller = "Error"
                }));
                return;
            }
        }
    }
}

How to Apply Filter on Controller

using System;
using Microsoft.AspNetCore.Mvc;
using WebApplication4.Filters;

namespace WebApplication4.Controllers
{
    [TypeFilter(typeof(CustomAsyncAuthorizationFilter))]
    public class DefaultController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

Conclusion

The Async Authorization Filter in ASP.NET Core MVC is a powerful mechanism when your authorization logic involves asynchronous tasks like querying a database. By implementing the IAsyncAuthorizationFilter interface, you gain flexibility and ensure non-blocking operations in your middleware pipeline.

In this example, we built a filter that:

  • Reads the UserId from the session
  • Uses a service to fetch the user’s role from the database asynchronously
  • Grants access only if the user has the “Admin” role
  • Redirects others to an access denied page

Let me know if you’d like this article formatted as a downloadable PDF or want a variation using claims-based authorization or policy-based filters.

By Saineshwar

Microsoft MVP for Developer Technologies | C# Corner MVP | Code project MVP | Senior Technical Lead | Author | Speaker | Love .Net | Full Stack developer | Open source contributor.