简体   繁体   中英

ASP.NET Core Authorization Policies: Can't step into the handler?

I have JWT-based claims authentication/ authorization set up in my .NET Core application, which authenticates as expected, but my policy enforcement is not acting as I would expect.

I have a requirements implementation and handler set up as follows:

public class ImpersonationRequirement : IAuthorizationRequirement
{
}

public class ImpersonationHandler : AuthorizationHandler<ImpersonationRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
        ImpersonationRequirement requirement)
    {
        if (context.User.CanImpersonate()) context.Succeed(requirement);

        return Task.CompletedTask;
    }
}

I have a helper set up like so:

public static bool CanImpersonate(
    this ClaimsPrincipal principal)
{
    var val = principal?.FindFirst(MyClaimTypes.CAN_IMPERSONATE)?.Value;
    return bool.TryParse(val, out var value) && value;
}

public class MyClaimTypes
{
    /// <summary>
    /// Boolean value indicating this user is authorized to impersonate other customer accounts.
    /// </summary>
    public const string CAN_IMPERSONATE = "cim";

    ...

    /// <summary>
    /// Actual name of the user impersonating the current user.
    /// </summary>
    public const string IMPERSONATING_USER = "imp";
}

...off of my Startup.cs , I have the policy defined:

services.AddAuthorization(options =>
{
    options.AddPolicy("Impersonator", policy => policy.Requirements.Add(new ImpersonationRequirement()));
});

...and on my controller, it's written as such:

[Produces("application/json")]
[Authorize(Policy = "Impersonator")]
public class ImpersonationController : Controller
{
    private readonly ILogger _logger;
    private readonly ITokenManagementService _tokenManagementService;
    private readonly UserManager<MyUser> _userManager;

    public ImpersonationController(ITokenManagementService tokenManagementService, ILoggerFactory loggerFactory, UserManager<MyUser> userManager)
    {
        _tokenManagementService = tokenManagementService;
        _userManager = userManager;
        _logger = loggerFactory.CreateLogger<ImpersonationController>();
    }

    [HttpPost]
    [Route("~/api/impersonation/token")]
    [ProducesResponseType(typeof(AuthenticationResponse), 200)]
    [ProducesResponseType(typeof(Exception), 500)]
    public async Task<IActionResult> Impersonate([FromBody] string userNameToImpersonate)
    {
        try
        {
            var impersonated = await _userManager.FindByNameAsync(userNameToImpersonate);
            if (impersonated == null) throw new EntityNotFoundException($"Unable to find user '{userNameToImpersonate}' in the data store.");
            var actualUserId = User.UserId();
            var token = await _tokenManagementService.GenerateJwt(impersonated.Id, actualUserId);
            var refresh = await _tokenManagementService.GenerateRefreshToken(impersonated.Id, actualUserId);
            var response = new AuthenticationResponse {AuthenticationToken = token, RefreshToken = refresh};
            return Ok(response);
        }
        catch (Exception ex)
        {
            return new OopsResult(ex);
        }
    }
}

If I run this with the AuthorizeAttribute commented out, I can take a look at the user's claims, and the "cim: true" is in the claims enumeration, but if I run it with the AuthorizeAttribute enabled, I get a 403 Forbidden error.

I tried putting a breakpoint on the line in the ImpersonationHandler :

if (context.User.CanImpersonate()) context.Succeed(requirement);

...but the debugger never stops here, so I don't know what the problem is. Can someone educate me as to what I'm doing wrong?

It seems you forgot to register your ImpersonationHandler in DI container (which is indeed easy to forget):

services.AddSingleton<IAuthorizationHandler, ImpersonationHandler>();

Asp.net resolves all such handlers from container and tries to match for specific requirement. Since no such handler is registered - nothing sets context.Succeed and whole authorization fails.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM