Custom Authorization Policy
다음과 같은 조건을 갖는 Policy를 만들어보자.
Member of the Admin role AND have Edit Role claim with a value of true
OR
Member of the Super Admin role
다음의 Policy로는 내가 원하는 Policy를 만들 수 없다. 조건 사이에는 AND condition만 있다.
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("EditRolePolicy", policy => policy
.RequireRole("Admin")
.RequireClaim("Edit Role", "true")
.RequireRole("Super Admin")
);
});
OR condition을 만들기 위해서는 RequireAssertion 함수를 사용한다.
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("EditRolePolicy", policy => policy.RequireAssertion(context =>
context.User.IsInRole("Admin") &&
context.User.HasClaim(claim => claim.Type == "Edit Role" && claim.Value == "true") ||
context.User.IsInRole("Super Admin")
));
});
Built-in asp.net core authorization requirements
- RequireClaims()
- RequireRole()
- RequireAssertion()
위의 requirements는 IAuthorizationRequirement 인터페이스를 구현한다. custom authorization requirement를 만들 때도, 동일하게 인터페이스를 구현해야 한다. authorization handler안에 접근처리에 대한 로직을 구현한다. authorization handler는 AuthorizationHandler<T>를 상속받고, HandlerRequirementAsync() 함수를 구현한다.
Custom Authorization Requirement & Handler
다음의 Requirement를 만들어보자.
Admin user는 다른 Admin user의 role, claim은 수정할 수 있지만 자신은 수정할 수 없다.
위의 요구사항을 처리하는 권한을 만들기 위해서는 query string parameter에 접근해야 한다. 따라서 built-in requirement는 사용할 수 없고, custom requirement & handler를 만들어야 한다.
ManageAdminRolesAndClaimsRequirement.cs
using Microsoft.AspNetCore.Authorization;
namespace Employee.Security
{
public class ManageAdminRolesAndClaimsRequirement : IAuthorizationRequirement
{
}
}
CanEditOnlyOtherAdminRolesAndClaimsHandler.cs
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Security.Claims;
namespace Employee.Security
{
public class CanEditOnlyOtherAdminRolesAndClaimsHandler : AuthorizationHandler<ManageAdminRolesAndClaimsRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ManageAdminRolesAndClaimsRequirement requirement)
{
var authFilterContext = context.Resource as AuthorizationFilterContext;
if (authFilterContext == null)
{
return Task.CompletedTask;
}
string loggedInAdminid = context.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value;
string adminIdBeingEdited = authFilterContext.HttpContext.Request.Query["userId"];
if (context.User.IsInRole("Admin") &&
context.User.HasClaim(claim => claim.Type == "Edit Role" && claim.Value == "true") &&
adminIdBeingEdited.ToLower() != loggedInAdminid.ToLower())
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
}
SuperAdminHandler.cs
using Microsoft.AspNetCore.Authorization;
namespace Employee.Security
{
public class SuperAdminHandler : AuthorizationHandler<ManageAdminRolesAndClaimsRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ManageAdminRolesAndClaimsRequirement requirement)
{
if (context.User.IsInRole("Super Admin"))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
}
Program.cs
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("EditRolePolicy",
policy => policy.AddRequirements(new ManageAdminRolesAndClaimsRequirement()));
});
builder.Services.AddSingleton<IAuthorizationHandler, CanEditOnlyOtherAdminRolesAndClaimsHandler>();
builder.Services.AddSingleton<IAuthorizationHandler, SuperAdminHandler>();
'ASP.NET Core' 카테고리의 다른 글
ASP.NET Core] 개발환경에서 Secret Manager(secrets.json) 사용 (0) | 2022.01.18 |
---|---|
ASP.NET Core] Authorization Handler (0) | 2022.01.17 |
ASP.NET Core 6] Service - AddTransient, AddScoped, AddSingleton 차이점 (0) | 2022.01.17 |
ASP.NET Core MVC 6] Authentication VS Authorization (0) | 2022.01.14 |
ASP.NET Core MVC 6] Identity 확장 (0) | 2022.01.13 |
댓글