I have a core 3.1 api running currently with JWT Bear Tokens. To use, I simple supply the token from an OAuth2 provider and this working fine.
The defaultPolicy is setup and uses RequireAuthenticatedUser();
However I have a require to allow for end-point that needs to use another authorization process.
So I created a custom AuthorizationHandler and added this as a policy. Then add this policy against the end point. When I hit that end point the custom AuthorizationHandler gets triggered and everything seems to work and the context.Succeed(requirement) is called and then returns Task.CompletedTask.
The problem is that I am still getting a 401 Unauthorize.
Can anyone help?
Below is the custom Handler:
public class MyCustomAuthorizeRequirement : IAuthorizationRequirement
{ }
public class MyCustomAuthorizeRequirementHandler : AuthorizationHandler<MyCustomAuthorizeRequirement>, IAuthorizationRequirement
{
private readonly MyCustomSettings _MyCustomSettings;
public MyCustomAuthorizeRequirementHandler(MyCustomSettings MyCustomSettings)
{
_MyCustomSettings = MyCustomSettings;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyCustomAuthorizeRequirement requirement)
{
var httpContext = context.Resource as HttpContext;
string authHeader = httpContext.Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("x-auth-"))
{
if(authHeader != _MyCustomSettings.MyCustomAuthKey)
{
context.Fail();
return Task.CompletedTask;
}
}
context.Succeed(requirement);
return Task.CompletedTask;
}
}
Below is the extract from the program.cs
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer();
// Configure policies
builder.Services
.AddAuthorization(options =>
{
var userAuthPolicyBuilder = new AuthorizationPolicyBuilder();
options.DefaultPolicy = userAuthPolicyBuilder
.RequireAuthenticatedUser()
.Build();
options.AddPolicy("MyCustomAuthorize", policy => policy.Requirements.Add(new MyCustomAuthorizeRequirement()));
});
MyCustomSettings localMyCustomSettings = new MyCustomSettings();
configuration.GetSection("MyCustomSettings").Bind(localMyCustomSettings);
builder.Services.AddSingleton<IAuthorizationHandler>(new MyCustomAuthorizeRequirementHandler(localMyCustomSettings));
CodePudding user response:
Remember, there are two "auth" related HTTP status codes: 401 and 403.
- 401 means "you don't have the right papers"
- 403 means "yes, these papers are legit, but I'm not allowed to let you in the door".
Your default policy has .RequireAuthenticatedUser()
. Keyword here is "Authenticated". Your application only has one authentication strategy - JWTs. If you don't provide a JWT, you are not authenticated, and thus not authorized.
Here's what you can do:
- Create another
AuthenticationHandler
that will read theAuthorization
header, ensure the value starts with "x-key-", and if so save it as a claim. - Modify your
AuthorizationHandler
to read from the claim (not directly from the HTTP request). - Modify the
AuthorizationPolicyBuilder
to have.AddAuthenticationSchemes()
, listing both schemes.