Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get user input parameters in my authorization policy requirement in ASP.NET Core 5.0?

I want to authorize users to see only their own resources (e.g: Audits entity). So in the AuditController I have:

[MyAuthorize(Policy = nameof(ValidUserToSeeAuditAuthorizationHandler))]
[HttpGet]
public async Task<JsonResult<AuditView>> GetByIdAsync(Guid id)
{
    // my business to fetch the audit info based by its id
    // ...      
    return result;
}

Then I created my Requirement and AuthorizationHandler classes:

public class ValidUserToSeeAuditRequirment : IAuthorizationRequirement
{
    public ValidUserToSeeAuditRequirment(Guid auditId)
    {
        auditId = auditId;
    }


    public Guid AuditId { get; }
}

public class ValidUserToSeeAuditAuthorizationHandler : AuthorizationHandler<ValidUserToSeeAuditRequirment>
{
    private readonly AppUserManager _userManager;
    private readonly IUnitOfWork _appDbContext;

    public ValidUserToSeeAuditAuthorizationHandler(AppUserManager userManager, IUnitOfWork appDbContext)
    {
        _userManager = userManager;
        _appDbContext = appDbContext;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidUserToSeeAuditRequirment requirement)
    {
        if (!context.User.IsAuthenticated())
        {
            context.Fail();
            return Task.CompletedTask;
        }

        var theAudit = _appDbContext.Set<Audit>().SingleOrDefault(x => x.Id == requirement.AuditId);
        var authenticatedUserId = Convert.ToInt32(context.User.GetSubjectId());
                    
        // If the authenticated user created the audit, then he/she is valid to see it
        if (theAudit.SubjectauthenticatedUserId == authenticatedUserId)
        {
            // valid
            context.Succeed(requirement);
            return Task.CompletedTask;
        }

        // he/she is not authorized to see the resource (audit)
        context.Fail();
        return Task.CompletedTask;
    }
}

But in the Startup class I want to configure authorization policies. How do I configure my Requirement class to get the user input parameters from the controller's action method?

services.AddAuthorization(options =>
{
    // another policies
    // ...
    
    options.AddPolicy(name: nameof(ValidUserToSeeAuditAuthorizationHandler),
        policy =>
        {
            policy.RequireAuthenticatedUser();
            policy.AddRequirements(new ValidUserToSeeAuditRequirment( /****** HERE, how to pass the controller action method parameters ******/));
        });
});

services.AddTransient<IAuthorizationHandler, ValidUserToSeeAuditAuthorizationHandler>();
like image 930
TheMah Avatar asked Oct 15 '25 04:10

TheMah


1 Answers

I ended up with this solution:

/// <summary>
/// 
/// </summary>
public class ValidUserToSeeAuditRequirment : IAuthorizationRequirement
{
    
}

/// <summary>
/// Only an Admin and the authorized user can see the Audit
/// </summary>
public class ValidUserToSeeAuditAuthorizationHandler : AuthorizationHandler<ValidUserToSeeAuditRequirment>
{
}

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidUserToSeeAuditRequirment requirement)
{
    // If he has the Admin Role, then he can see the Audit
    if (context.User.HasClaim(x => "role".Equals( x.Type, StringComparison.OrdinalIgnoreCase ) && "admin".Equals( x.Value, StringComparison.OrdinalIgnoreCase ))
    {
        context.Succeed(requirement);
        return;
    }

    // Get the audit id from the Routing
    var auditIdFromRoute = context.HttpContext.GetRouteData()?.Values["id"].ToString();
    if (auditIdFromRoute is null || !Guid.TryParse(auditIdFromRoute, out Guid requestingAuditId))
    {
        context.Fail();
        return;
    }

    // get the authenticated user
    var userId = Convert.ToInt32(context.User.GetSubjectId());
        
    // check if the user has authorized to see the audit
    if(isUserAllowToSeeAudit(userId, requestingAuditId))
    {
        context.Succeed(requirement);
        return;
    }
    
    context.Fail();
}

private bool isUserAllowToSeeAudit(int userId, Guid auditId)
{
    // ...
}
like image 92
TheMah Avatar answered Oct 16 '25 17:10

TheMah



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!