Reputation: 824
I have two policy in place the ApiUser and CompanyBased. when I am using the companybased policy ([Authorize(Policy = "CompanyBased")] ) the application is failing to validate the JWT token. When I am using [Authorize] it works well, the token is validated...
Version: core 2.2
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3] Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'. Microsoft.AspNetCore.Mvc.ForbidResult[1] Executing ForbidResult with authentication schemes (). Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[13] AuthenticationScheme: Bearer was forbidden.
// api user claim policy
services.AddAuthorization(options =>
{
options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
options.AddPolicy("CompanyBased", policy =>
{
policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess);
policy.AddRequirements(new CompanyBasedRequirement());
});
});
This is the CompanyBasedHandler
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CompanyBasedRequirement requirement)
{
#region Validate Company id
Guid? companyId = _httpContextAccessor.HttpContext.Request.Headers.GetCompanyId();
string nameIdentifier = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
if (companyId is null)
{
_logger.LogInformation($"No company suppied for {nameIdentifier}");
context.Fail();
}
else
{
if (!_clientRepository.IsClientValid(companyId.Value, nameIdentifier))
{
_logger.LogInformation($"{companyId} does not belong to {nameIdentifier}");
context.Fail();
}
else
{
context.Succeed(requirement);
}
}
#endregion Validate Company id
return Task.CompletedTask;
}
Upvotes: 0
Views: 870
Reputation: 824
I was missing the Constants.Strings.JwtClaimIdentifiers.Rol in the token!
Upvotes: 0
Reputation: 7205
Make sure that you regisered your custom authorization handler correctly in your dependency injection container in the Startup class. It should be registered as a singleton:
services.AddSingleton<IAuthorizationHandler, CompanyBasedHandler>();
You can make the HandleRequirementAsync
async/await by changing the the method signature to async Task
and then not returning a completed Task at the end of the method, for example:
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, CompanyBasedRequirement requirement)
{
#region Validate Company id
Guid? companyId = _httpContextAccessor.HttpContext.Request.Headers.GetCompanyId();
string nameIdentifier = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
if (companyId is null)
{
_logger.LogInformation($"No company suppied for {nameIdentifier}");
context.Fail();
}
else
{
if (!_clientRepository.IsClientValid(companyId.Value, nameIdentifier))
{
_logger.LogInformation($"{companyId} does not belong to {nameIdentifier}");
context.Fail();
}
else
{
context.Succeed(requirement);
}
}
#endregion Validate Company id
}
Note that you are not doing any asynchronous operations in the method, that means it will run synchronously thus there is not need to make this method async.
Upvotes: 1