// https://stackoverflow.com/questions/31464359/how-do-you-create-a-custom-authorizeattribute-in-asp-net-core?rq=1 public class ClaimRequirementAttribute : TypeFilterAttribute { public ClaimRequirementAttribute(string claimType, string claimValue) : base(typeof(ClaimRequirementFilter)) { Arguments = new object[] {new Claim(claimType, claimValue) }; } } public class ClaimRequirementFilter : IAuthorizationFilter { readonly Claim _claim; public ClaimRequirementFilter(Claim claim) { _claim = claim; } public void OnAuthorization(AuthorizationFilterContext context) { var hasClaim = context.HttpContext.User.Claims.Any(c => c.Type == _claim.Type && c.Value == _claim.Value); if (!hasClaim) { context.Result = new ForbidResult(); } } } [Route("api/resource")] public class MyController : Controller { [ClaimRequirement(MyClaimTypes.Permission, "CanReadResource")] [HttpGet] public IActionResult GetResource() { return Ok(); } } //// // The security team for .net is kinda jr: // "We don't want you writing custom authorize attributes. If you need to do that we've done something wrong. Instead, you should be writing authorization requirements". // Thats bad. They are not thinking about the amount of work they are creating for other people instead of designing a system that makes it easy like they should be; they are just so jr level that they cant design a system that makes things easy to do the right way. // In thier system: Authorization acts upon Identities. Identities are created by authentication. This violates a lot of security stuff and oversimplifies the model. // They want you to write the following code over and over fir every new app instead of doing it the smart way: public class Over18Requirement : AuthorizationHandler, IAuthorizationRequirement { public override void Handle(AuthorizationHandlerContext context, Over18Requirement requirement) { if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth)) { context.Fail(); return; } var dobVal = context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth).Value; var dateOfBirth = Convert.ToDateTime(dobVal); int age = DateTime.Today.Year - dateOfBirth.Year; if (dateOfBirth > DateTime.Today.AddYears(-age)) { age--; } if (age >= 18) { context.Succeed(requirement); } else { context.Fail(); } } } // Then in your ConfigureServices() function you'd wire it up services.AddAuthorization(options => { options.AddPolicy("Over18", policy => policy.Requirements.Add(new Authorization.Over18Requirement())); }); // And finally, apply it to a controller or action method with [Authorize(Policy = "Over18")] // So basiclly its just roles as policies but you have to do the work because that team is too scared to write secure code.