Reputation:
In MVC Core, following code displays how to conduct role based authorization.
Eg: people in HR and Finance can access.
How do I parametize Roles below for deployment with variables without changing the source code? Eg next week, Roles will be replaced by "Accounting" and "Marketing".
Reading MSDN article: Role-based authorization in ASP.NET Core
[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{
}
Upvotes: 0
Views: 267
Reputation: 3569
This is also a matter of design: if you think of roles as user groups, you end up with such situations; as environment changes (or you deploy it elsewhere), you will need to reposition your authorization settings. But if you can have hierarchic roles, you don't need that anymore. Let me explain: you set role Salary to SalaryController. In your role management, just add the to Salary role (group) the groups HRManager and Finance. And you can add users to these later. You will never need to change the code to change the actual people who can reach the function (U=G=F). Just never add users directly to Salary group - it would work, but it messes up the concept. If there is no group to group membership in the role management behind then... well, then you should try to replace it anyway, as it is not the best.
If you have Active Directory in a corporate environment (where else?) where the roles are AD security groups - you might be facing the fact, that there are corporate policies on how to name those groups. And that will differ from corporate to corporate. To handle this, you should still choose your role names to express the functionality instead of a user group. But you will need to map between the role and the group corresponding to the role (this is actually one layer on top of the concept from above: U=G=G-F). Thus in your code, you would use the functionality or role names you whish, but behind the scenes, everything would be translated in AD group membership. I have written an authorization filter that handles latter scenario, and I am happily sharing it with you if you need it - you have tagged your question with asp.net-mvc. For asp.net-core @Kahbazi's answer is the way to go (more here).
Upvotes: 0
Reputation: 15015
You should use Policy
and write your own AuthorizationHandler
.
Here's a sample how can you do it:
appsettings.json
{
"Auth": {
"Role": "User"
}
}
startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(cfg =>
{
cfg.AddPolicy("dynamicRole", b => b.Requirements.Add(new DynamicRole()));
});
services.AddScoped<IAuthorizationHandler, DynamicRoleHandler>();
services.Configure<AuthorizationOptions>(Configuration.GetSection("Auth"));
}
}
DynamicRole.cs
public class DynamicRole : IAuthorizationRequirement
{
}
AuthorizationOptions.cs
public class AuthorizationOptions
{
public string Role { get; set; }
}
DynamicRoleHandler.cs
public class DynamicRoleHandler : AuthorizationHandler<DynamicRole>
{
private readonly AuthorizationOptions _options;
public DynamicRoleHandler(IOptionsMonitor<AuthorizationOptions> options)
{
_options = options.CurrentValue;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DynamicRole requirement)
{
if (context.User.IsInRole(_options.Role))
{
context.Succeed(requirement);
}
else
{
context.Fail();
}
return Task.CompletedTask;
}
}
TestController.cs
public class TestController : Controller
{
[Authorize(policy: "dynamicRole")]
public string Test()
{
return "Hello World!";
}
}
Upvotes: 1
Reputation: 96
Not the most beautiful way of doing it xD
[Authorize(Roles = SomeClassName.DynamicRoles)]
public class SalaryController : Controller
{
}
And make a static class like
public static class SomeClassName
{
public const string DynamicRoles = "HRManager, Finance";
}
Upvotes: 0