Trying to implement policy authorization in a .NET6 Web Api.
I've added in authentication and authorization via the configuration:
builder.AddCredibleApplicationFramework(assemblies);
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme,
options =>
{
var tokenValidationSettings = builder.Configuration.GetSection("JwtSettings")
.Get<TokenValidationSettings>();
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = tokenValidationSettings.ValidateIssuer,
ValidateAudience = tokenValidationSettings.ValidateAudience,
ValidateIssuerSigningKey = true,
ValidIssuer = tokenValidationSettings.Issuer,
IssuerSigningKey =
new SymmetricSecurityKey(Encoding.ASCII.GetBytes(tokenValidationSettings.SigningKey))
};
});
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("isAdministrator",
policyBuilder =>
{
policyBuilder.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policyBuilder.AddRequirements(new IsAdministratorRequirement());
});
});
builder.Services.AddSingleton<IAuthorizationHandler, IsApplicationAdministratorHandler>();
builder.Services.AddDbContext<CDbContext>(options =>
{
var connection = builder.Configuration.GetConnectionString("conn");
options
.UseMySql(connection, ServerVersion.AutoDetect(connection))
.EnableSensitiveDataLogging()
.EnableDetailedErrors()
.UseLoggerFactory(loggerFactory);
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthentication();
app.UseAuthorization();
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
The handler success path is executing (the requirement succeeds):
public class IsApplicationAdministratorHandler : AuthorizationHandler<IsAdministratorRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
IsAdministratorRequirement requirement)
{
if (context.User.HasClaim(c => c.Type.Equals("applicationAdmin")) ||
context.User.HasClaim(c => c.Type.Equals("platformAdmin")))
{
return Task.FromResult(() => context.Succeed(requirement)); <-- This line returns....
}
return Task.FromResult(() => context.Fail());
}
}
I am getting 403 even though the handler succeeds.
CodePudding user response:
You are returning a lambda result rather than calling the actual context method, since your lambda is never executed. Its not necessary in your case, as you can directly call context.Succeed(requirement)
public class IsApplicationAdministratorHandler : AuthorizationHandler<IsAdministratorRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
IsAdministratorRequirement requirement)
{
if (context.User.HasClaim(c => c.Type.Equals("applicationAdmin")) ||
context.User.HasClaim(c => c.Type.Equals("platformAdmin")))
{
context.Succeed(requirement);
}
else
{
// this isn't strictly necessary, unless you want to fail hard and early
// and not give other policy handlers to be evaluated
context.Fail(requirement)
};
return Task.Completed;
}
}