Authorize attribute with multiple roles

I would like to add authorization to the controller for several roles at once.

Usually it will look like this:

[Authorize(Roles = "RoleA,RoleB,RoleC")] public async Task<ActionResult> Index() { } 

But I kept my roles in const, as they can be changed or expanded at some point.

 public const RoleA = "RoleA"; public const RoleB = "RoleB"; public const RoleC = "RoleC"; 

I cannot do this, since the string must be known at compile time:

 [Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)] public async Task<ActionResult> Index() { } 

Is there a way around the problem?

I CAN write a const that simply contains "RoleA, RoleB, RoleC", but I don't like magic lines, and this is a magic line. Changing the role name and forgetting to change the combo string would be a disaster.

I am using MVC5. The ASP.NET identifier and role are known at compile time.

+74
c # authorization asp.net-mvc
Jun 12 '14 at 10:14
source share
6 answers

Try creating a custom authorization attribute, for example.

 public class AuthorizeRolesAttribute : AuthorizeAttribute { public AuthorizeRolesAttribute(params string[] roles) : base() { Roles = string.Join(",", roles); } } 

Assuming your roles are the same for multiple controllers, create a helper class:

 public static class Role { public const string Administrator = "Administrator"; public const string Assistant = "Assistant"; } 

Then use it like this:

 public class MyController : Controller { [AuthorizeRoles(Role.Administrator, Role.Assistant)] public ActionResult AdminOrAssistant() { return View(); } } 
+141
Jun 12 '14 at 10:39
source share

Make sure you select your own attribute class System.Web.Mvc.AuthorizeAttribute and NOT System.Web.Http.AuthorizeAttribute .

I ran into the same problem. As soon as I changed it, everything worked.

You can also add the following to your own attribute class:

 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 
+8
Aug 07 '16 at 4:05
source share

The best and easiest way I've found to solve this problem is to simply combine the roles in the Authorize attribute.

 [Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)] 

with a CustomRole class with constant lines like this:

 public static class CustomRoles { public const string Admin = "Admin"; // and so on.. } 
+6
Mar 01 '17 at 15:44
source share

What I did was answer in @Tieson

I tweaked his answer a bit. Instead of a string. Join us, why not convert it to a list?

Here is my answer:

 public class AuthorizeRolesAttribute : AuthorizeAttribute { private new List<string> Roles; public AuthorizeRolesAttribute(params string[] roles) : base() { Roles = roles.toList() } } 

And then check if the role really overrides OnAuthorization.

 public override void OnAuthorization(HttpActionContext actionContext) { if (Roles == null) HandleUnauthorizedRequest(actionContext); else { ClaimsIdentity claimsIdentity = HttpContext.Current.User.Identity as ClaimsIdentity; string _role = claimsIdentity.FindFirst(ClaimTypes.Role).Value; bool isAuthorize = Roles.Any(role => role == _role); if(!isAuthorize) HandleUnauthorizedRequest(actionContext); } } 

And now, you have it, now it checks if the role is authorized to access the resource.

+1
Mar 08 '18 at 1:35
source share

I feel that the special authorize attribute is redundant for this problem if you don't have a lot of roles.

Since the line should be known at compile time, why not create a static role class that contains the public lines of the roles you define, and then add lines separated by commas, with specific roles that you want to allow:

 public static class Roles { public const string ADMIN = "Admin"; public const string VIEWER = "Viewer"; public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER; } 

And then you can use the authorization attribute, for example, in the controller class or controller method (or both):

 [Authorize(Roles = Roles.ADMIN] public class ExampleController : Controller { [Authorize(Roles = Roles.ADMIN_OR_VIEWER) public ActionResult Create() { ..code here... } } 
0
Aug 12 '17 at 21:02
source share

What Tieson's answer does is just like that =

[Authorize (Roles = "Role1, Role2")]

checked, works.

0
Dec 10 '18 at 19:52
source share



All Articles