ASP.NET CORE - How to using IAuthorizationRequirementData

Published: (December 12, 2025 at 11:58 PM EST)
2 min read
Source: Dev.to

Source: Dev.to

Scenarios may be useful

  • Using an external service to provide policy evaluation.
  • Using a large range of policies, so it doesn’t make sense to add each individual authorization policy with an AuthorizationOptions.AddPolicy call.
  • Creating policies at runtime based on information in an external data source (like a database) or determining authorization requirements dynamically through another mechanism.

Applied: from ASP.NET Core 8

Step 1: Implement a custom Authorize attribute

using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;

namespace PracticalAPI.AuthorizationRequirementData
{
    public enum FeatureOperator
    {
        And = 1,
        Or = 2
    }

    public class UserFeatureAuthorizeAttribute : AuthorizeAttribute,
        IAuthorizationRequirement,
        IAuthorizationRequirementData
    {
        internal const string PolicyPrefix = "UserFeature_";
        public FeatureOperator Operator { get; set; }
        public string[] Features { get; set; }

        public UserFeatureAuthorizeAttribute(FeatureOperator featureOperator, params string[] features)
        {
            Operator = featureOperator;
            Features = features;
        }

        public UserFeatureAuthorizeAttribute(string feature)
        {
            Operator = FeatureOperator.And;
            Features = new[] { feature };
        }

        public IEnumerable GetRequirements()
        {
            yield return this;
        }
    }
}

Step 2: Implement the AuthorizationHandler

using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using System.Globalization;
using System.Threading.Tasks;
using System;

namespace PracticalAPI.AuthorizationRequirementData
{
    public class UserFeatureAuthorizationHandler : AuthorizationHandler
    {
        private readonly ILogger _logger;
        private static string featureType = "feature";

        public UserFeatureAuthorizationHandler(ILogger logger)
        {
            _logger = logger;
        }

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                         UserFeatureAuthorizeAttribute requirement)
        {
            if (requirement.Operator == FeatureOperator.And)
            {
                foreach (var feature in requirement.Features)
                {
                    _logger.LogWarning("Evaluating authorization requirement for feature: {Feature}", feature);
                    if (!context.User.HasClaim(featureType, feature))
                    {
                        context.Fail();
                        return Task.CompletedTask;
                    }
                }

                context.Succeed(requirement);
                return Task.CompletedTask;
            }

            foreach (var feature in requirement.Features)
            {
                _logger.LogWarning("Evaluating authorization requirement for feature: {Feature}", feature);
                if (context.User.HasClaim(featureType, feature))
                {
                    context.Succeed(requirement);
                    return Task.CompletedTask;
                }
            }

            context.Fail();
            return Task.CompletedTask;
        }
    }
}

Step 3: Register the UserFeatureAuthorizationHandler

using AuthRequirementsData.Authorization;
using Microsoft.AspNetCore.Authorization;

var builder = WebApplication.CreateBuilder();
// ...
// Use custom authorization
// builder.Services.AddSingleton();

var app = builder.Build();

app.MapControllers();

app.Run();

Step 4: Use the custom authorization attribute in a controller

[UserFeatureAuthorize("Feature1")]
public async Task> MyAction([FromBody] RequestModel model)
{
    // Logic code goes here
}

This is one of many options you can use to implement robust authorization for your application. Choose the approach that best fits your scenario.

Happy coding!

Back to Blog

Related posts

Read more »