In ASP.NET Core MVC, authorization is performed using the AuthorizeAttribute
class. Here’s a simple example using role-based authorization:
[Authorize(Roles = "Admin,Moderator")]
public class AdminController : Controller
{
// ...
}
Users with the Admin
or the Moderator
role will have access to the actions in the AdminController
.
While there’s nothing wrong with this, and it gets the job done, the "Admin,Moderator"
string—like you might imagine—is a good recipe for a typo. So let’s move the role names to a set of string constants:
public static class RoleConstants
{
public const string Admin = "Admin";
public const string Moderator = "Moderator";
// more roles
}
The AdminController
now becomes:
[Authorize(Roles=RoleConstants.Admin+","+RoleConstants.Moderator)]
public class AdminController : Controller
{
// ...
}
Not ideal, I know. Unfortunately, we can’t use interpolated strings like $"{RoleConstants.Admin},{RoleConstants.Moderator}"
with attributes.
This is a good example where extending the AuthorizeAttribute
class makes sense. Since we’re trying to make it easier to call for role-based authorization on a controller or action, let’s create a custom AuthorizeByRoleAttribute
:
/// <summary>
/// Specifies that the class or method that this attribute is applied to requires role-based authorization. <br />
/// To authorize users with either role A or role B, use:
/// <code>
/// [AuthorizeByRole("A", "B")]
/// </code>
/// To only authorize users with both role A and role B, use:
/// <code>
/// [AuthorizeByRole("A")] <br />
/// [AuthorizeByRole("B")]
/// </code>
/// </summary>
public class AuthorizeByRoleAttribute : AuthorizeAttribute
{
public MyAuthorizeAttribute(params string[] roles)
{
Roles = String.Join(",", roles);
}
}
We can use it as follows:
[AuthorizeByRole(RoleConstants.Admin, RoleConstants.Moderator)]
public class AdminController : Controller
{
// ...
}
So much better, right?
If you’re coming from the full-framework ASP.NET MVC, you’ll know how it was possible to override methods from the AuthorizeAttribute
to add custom authorization behavior. You can’t do that in ASP.NET Core. (Source for ASP.NET MVC | Source for ASP.NET Core)
If you need custom authorization behavior, use policies. Barry Dorrans (the ASP.NET Security “Czar” at Microsoft) talks about it in a 2017 .NET Rocks podcast around the 30-minute mark—worth listening to if you’re interested in some background.
Customizing [Authorize]
by extending it is pretty straightforward, but only makes sense if you’re trying to make the code a little more maintainable. For custom behavior you want to be using ASP.NET Core policies instead.
Galdin Raphael is an independent software developer. When not writing code, he's probably reading a book, playing the piano or studying music theory. Follow him on
twitter: @gldraphael