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

Jeremy Holovacs

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?

Evk

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.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

ASP.NET Core can't step into endpoint method?

ServiceStack on .NET Core using Authorization Policies

Authorization failing for custom authentication handler for ASP.NET Core 3.1?

Asp.Net Core Razor Pages authorization handlers for policies with Authorize attribute on PageModel still run after executing policies set to folders

Is it safe to use .RequireRole() without .RequireAuthenticatedUser() in ASP.NET Core authorization policies?

Asp Core MVC 2.1 Authorization based on policies per user?

ASP .NET Core use multiple CORS policies

How to avoid repetitive conditions in authorization policies in .NET Core

Any way to use Authorization Policies in a view in .NET Core 1.0 MVC?

Which authorization policy is used if multiple policies are specified (e.g. middleware configuration, controller/action attribute,) in Asp.Net Core?

Can't add a simple POST handler to an ASP.NET Core MVC web app

Can I route ASP.NET Core login to different Azure B2C policies?

ASP.NET Can't Implement Authentication/Authorization

Hierarchical policies / requirements in ASP.NET Core Identity

Asp Net Core 3.1 Authorization by Custom Roles

ASP.Net Core 5.0 Authentication and Authorization

Asp net core MVC Authorization with Active Directory

ASP.NET Core 5.0 Customizing Authorization

Claim based authorization in ASP.NET Core

ASP.NET Core with optional authentication/authorization

Authorization in ASP .NET Core Razor pages

OAuth Authorization Service in ASP.NET Core

Authorization token not binding in ASP.NET Core

About authorization in ASP.NET Core

Asp.NET Core Claim based Authorization

Claims based authorization in ASP.NET Core

Custom Authorization attribute asp.net core

Dynamic authorization of roles asp.net core

ASP.NET Core 2.2 Authorization not authorizing

TOP Ranking

  1. 1

    Failed to listen on localhost:8000 (reason: Cannot assign requested address)

  2. 2

    pump.io port in URL

  3. 3

    How to import an asset in swift using Bundle.main.path() in a react-native native module

  4. 4

    Loopback Error: connect ECONNREFUSED 127.0.0.1:3306 (MAMP)

  5. 5

    Compiler error CS0246 (type or namespace not found) on using Ninject in ASP.NET vNext

  6. 6

    BigQuery - concatenate ignoring NULL

  7. 7

    Spring Boot JPA PostgreSQL Web App - Internal Authentication Error

  8. 8

    ggplotly no applicable method for 'plotly_build' applied to an object of class "NULL" if statements

  9. 9

    ngClass error (Can't bind ngClass since it isn't a known property of div) in Angular 11.0.3

  10. 10

    How to remove the extra space from right in a webview?

  11. 11

    Change dd-mm-yyyy date format of dataframe date column to yyyy-mm-dd

  12. 12

    Jquery different data trapped from direct mousedown event and simulation via $(this).trigger('mousedown');

  13. 13

    maven-jaxb2-plugin cannot generate classes due to two declarations cause a collision in ObjectFactory class

  14. 14

    java.lang.NullPointerException: Cannot read the array length because "<local3>" is null

  15. 15

    How to use merge windows unallocated space into Ubuntu using GParted?

  16. 16

    flutter: dropdown item programmatically unselect problem

  17. 17

    Pandas - check if dataframe has negative value in any column

  18. 18

    Nuget add packages gives access denied errors

  19. 19

    Can't pre-populate phone number and message body in SMS link on iPhones when SMS app is not running in the background

  20. 20

    Generate random UUIDv4 with Elm

  21. 21

    Client secret not provided in request error with Keycloak

HotTag

Archive