.Net 5 Check CustomPolicy from Razor Page

Viewed 41

I have a custom authorization handler as below:

public class CanApproveArticlesByOtherAuthorsClaimsHandler : AuthorizationHandler<ManageArticleApprovalRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ManageArticleApprovalRequirement requirement)
    {
        var httpContext = context.Resource as HttpContext;

        if (httpContext == null)
        {
            return Task.CompletedTask;
        }

        string loggedInUser = context.User.Claims
                                          .FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value;
        string authorId = (string)httpContext.Request.RouteValues["authorid"];

        if (context.User.IsInRole("Admin")
            && context.User.HasClaim(claim => claim.Type == "Article Approver" && claim.Value == "true")
            && loggedInUser.ToLower() != authorId.ToLower())
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

I need to check if this policy is a success when I load edit.cshtml and determine if I need to load a control on the page. This is what I have now, but I want to use the custom policy.

        @if ((await authService.AuthorizeAsync(User, null, new[] { new ManageArticleApprovalRequirement() })).Succeeded)
    {
        <div class="col-sm-3 offset-sm-2">
            <input asp-for="@Model.Approved" class="form-check-input" />
            <label class="form-check-label" asp-for="@Model.Approved">Approve For Publication</label>
        </div>
    }

And in Startup.cs

            services.AddSingleton<IAuthorizationHandler, CanApproveOnlyArticlesByOtherAuthorsHandler>();

and

            services.AddAuthorization(options =>
        {
            //Other code

            options.AddPolicy("ApproveArticlesPolicy", policy => policy.AddRequirements(new ManageArticleApprovalRequirement()));

            //Other code;

        });
1 Answers

You can use the IAuthorizationService directly to authorize against a user with some requirement, like this:

@inject IAuthorizationService _authService;

<!-- the code section that need to authorize -->
<!-- for razor view, pass in Context instead of ViewContext.HttpContext 
     for the resource -->
@if((await _authService.AuthorizeAsync(User, ViewContext.HttpContext, new [] { new ManageArticleApprovalRequirement() })).Succeeded){
    <div class="col-sm-3 offset-sm-2">
        <input asp-for="@Model.Approved" class="form-check-input" />
        <label class="form-check-label" asp-for="@Model.Approved">Approve For Publication</label>
    </div>
}

Note I assume that your ManageArticleApprovalRequirement has a parameterless constructor. Basically you need to pass an instance of that requirement to the IAuthorizationService.AuthorizeAsync method as the code above shows.

Related