I'm trying to make a custom authorization attribute in ASP.NET Core. In previous versions it was possible to override bool AuthorizeCore(HttpContextBase httpContext)
. But this no longer exists in AuthorizeAttribute
.
What is the current approach to make a custom AuthorizeAttribute?
What I am trying to accomplish: I am receiving a session ID in the Header Authorization. From that ID I'll know whether a particular action is valid.
The approach recommended by the ASP.Net Core team is to use the new policy design which is fully documented here. The basic idea behind the new approach is to use the new [Authorize] attribute to designate a "policy" (e.g.
[Authorize( Policy = "YouNeedToBe18ToDoThis")]
where the policy is registered in the application's Startup.cs to execute some block of code (i.e. ensure the user has an age claim where the age is 18 or older).The policy design is a great addition to the framework and the ASP.Net Security Core team should be commended for its introduction. That said, it isn't well-suited for all cases. The shortcoming of this approach is that it fails to provide a convenient solution for the most common need of simply asserting that a given controller or action requires a given claim type. In the case where an application may have hundreds of discrete permissions governing CRUD operations on individual REST resources ("CanCreateOrder", "CanReadOrder", "CanUpdateOrder", "CanDeleteOrder", etc.), the new approach either requires repetitive one-to-one mappings between a policy name and a claim name (e.g.
options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));
), or writing some code to perform these registrations at run time (e.g. read all claim types from a database and perform the aforementioned call in a loop). The problem with this approach for the majority of cases is that it's unnecessary overhead.While the ASP.Net Core Security team recommends never creating your own solution, in some cases this may be the most prudent option with which to start.
The following is an implementation which uses the IAuthorizationFilter to provide a simple way to express a claim requirement for a given controller or action:
I'm the asp.net security person.
Firstly let me apologise that none of this is documented yet outside of the musicstore sample or unit tests, and it's all still being refined in terms of exposed APIs.Detailed documentation is here.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.
Authorization acts upon Identities. Identities are created by authentication.
You say in comments you want to check a session ID in a header. Your session ID would be the basis for an identity. If you wanted to use the
Authorize
attribute you'd write an authentication middleware to take that header and turn it into an authenticatedClaimsPrincipal
. You would then check that inside an authorization requirement. Authorization requirements can be as complicated as you like, for example here's one that takes a date of birth claim on the current identity and will authorize if the user is over 18;Then in your
ConfigureServices()
function you'd wire it upAnd finally apply it to a controller or action method with
Based on Derek Greer GREAT answer, i did it with enums.
Here is an example of my code:
You can create your own AuthorizationHandler that will find custom attributes on your Controllers and Actions, and pass them to the HandleRequirementAsync method.
Then you can use it for any custom attributes you need on your controllers or actions. For example to add permission requirements. Just create your custom attribute.
Then create a Requirement to add to your Policy
Then create the AuthorizationHandler for your custom attribute, inheriting the AttributeAuthorizationHandler that we created earlier. It will be passed an IEnumerable for all your custom attributes in the HandleRequirementsAsync method, accumulated from your Controller and Action.
And finally, in your Startup.cs ConfigureServices method, add your custom AuthorizationHandler to the services, and add your Policy.
Now you can simply decorate your Controllers and Actions with your custom attribute.
Easy: don't create your own
AuthorizeAttribute
.For pure authorization scenarios (like restricting access to specific users only), the recommended approach is to use the new authorization block: https://github.com/aspnet/MusicStore/blob/1c0aeb08bb1ebd846726232226279bbe001782e1/samples/MusicStore/Startup.cs#L84-L92
For authentication, it's best handled at the middleware level.
What are you trying to achieve exactly?
It seems that with ASP.NET Core 2, you can again inherit
AuthorizeAttribute
, you just need to also implementIAuthorizationFilter
: