AddJwtBearer OnAuthenticationFailed return custom error
It's important to note that both the aspnet-contrib OAuth2 validation and the MSFT JWT handler automatically return a WWW-Authenticate
response header containing an error code/description when a 401 response is returned:
If you think the standard behavior is not convenient enough, you can use the events model to manually handle the challenge. E.g:
services.AddAuthentication()
.AddJwtBearer(options =>
{
options.Authority = "http://localhost:54540/";
options.Audience = "resource_server";
options.RequireHttpsMetadata = false;
options.Events = new JwtBearerEvents();
options.Events.OnChallenge = context =>
{
// Skip the default logic.
context.HandleResponse();
var payload = new JObject
{
["error"] = context.Error,
["error_description"] = context.ErrorDescription,
["error_uri"] = context.ErrorUri
};
context.Response.ContentType = "application/json";
context.Response.StatusCode = 401;
return context.Response.WriteAsync(payload.ToString());
};
});
Was facing same issue, tried the solution provided by Pinpoint but it didnt work for me on ASP.NET core 2.0. But based on Pinpoint's solution and some trial and error, the following code works for me.
var builder = services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.Authority = "http://192.168.0.110/auth/realms/demo";
o.Audience = "demo-app";
o.RequireHttpsMetadata = false;
o.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = c =>
{
c.NoResult();
c.Response.StatusCode = 500;
c.Response.ContentType = "text/plain";
c.Response.WriteAsync(c.Exception.ToString()).Wait();
return Task.CompletedTask;
},
OnChallenge = c =>
{
c.HandleResponse();
return Task.CompletedTask;
}
};
});