Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check authorization policy inside the action controller

Because of the API is shared with admin and user. So I want to check the policy inside the action if the user id not equal with the parameter.

To simplify, this application using jwt token as the access token. So as for now have 2 roles which it User and Admin. So I add policy based on claims for this roles. Here how I generate the policy in startup.cs

public static IServiceCollection AddCustomAuthorizationPolicy(this IServiceCollection services) 
{
    services.AddAuthorization(options = >options.AddPolicy("UserOnly", policy = >policy.RequireClaim(CustomClaimTypes.UserManagement, "User", "Admin")));
    services.AddAuthorization(options = >options.AddPolicy("RequireAdmin", policy = >policy.RequireClaim(CustomClaimTypes.UserManagement, "Admin")));

    return services;
}

UserOnly allow both of roles. RequireAdmin for admin only.

Here is the current API I do for change the password

[HttpPost("{id}/change-password")]
[Authorize(Policy = "RequireAdmin")]
public async Task <IActionResult> ChangePassword([FromRoute] string id, [FromBody] UserChangePasswordViewModel model) 
{
    
    //This authorize filter require admin.
    //But I also want allow user to access
    
    var user = await _userManager.FindByIdAsync(id);

    if (user == null) return BadRequest("User not found");
    
    //My business logic here

}

So I change to UserOnly which allow both of roles to access it

[HttpPost("{id}/change-password")]
[Authorize(Policy = "UserOnly")]
public async Task < IActionResult > ChangePassword([FromRoute] string id, [FromBody] UserChangePasswordViewModel model) 
{
    var getCurrentUserId = _identityService.GetUserIdentity();
    
    var user = await _userManager.FindByIdAsync(id);

    if (user == null) return BadRequest("User not found");
    
    if(getCurrentUserId != id)
    {
        //Check if this user is admin
        if(!isAdmin) //<-- Here I want to check the policy
        {
            //Response 403 forbidden
            
        }
    }

    //My business logic here

}

But I not really sure how to check policy inside the action. Any better suggestion? or need to use HttpContext.User for find the claim and check the value?

like image 309
Azri Zakaria Avatar asked Oct 20 '25 10:10

Azri Zakaria


2 Answers

You can make a dynamic policy decision by taking a dependency in your controller on IAuthorizationService and calling the IAuthorizationService.AuthorizeAsync method. An example of some fictional controller:

private readonly IAuthorizationService _authorizationService;

public MyController(IAuthorizationService authorizationService) 
{
    _authorizationService = authorizationService;
}

[HttpPost("{id}/protected-action")]
public async Task <IActionResult> SomeDynamicallyProtectedAction() 
{
    var isAdminEvaluationResult =
        await _authorizationService.AuthorizeAsync(User, null, "RequireAdmin");

    if (!isAdminEvaluationResult.Succeeded)
    {
        return Forbid();
    }

    // ...continue processing the request
}
like image 101
Pablissimo Avatar answered Oct 21 '25 23:10

Pablissimo


Try: User.IsInRole("Admin")

like image 43
Łukasz K Avatar answered Oct 21 '25 23:10

Łukasz K