JWTBearerHandler 令牌失败但请求仍在处理中
JWT BearerHandler Token Falied but request is still processed
我 运行 遇到了一个非常奇怪的问题,我猜我在我的设置中遗漏了一些东西。
我有一个由 IdentityServer4 保护的 WebAPI。它仅使用 Client_credentials。如果我写错了 ClientId och ClientSecret 用户未通过身份验证,我将无法连接到我的 WebAPI。但是,如果我写错了范围名称,请求仍会得到处理,并且我会收到响应,奇怪的是会抛出异常,但由于某种原因,它会被 .NET Core Framework 忽略。
这是我输出的一些调试信息 window。
Microsoft.AspNetCore.Hosting.Internal.WebHost:信息:请求开始 HTTP/1.1 GET https://localhost:44360/v1/bookings
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: Failed to validate the token.
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidAudienceException: IDX10214: Audience validation failed. Audiences: '[PII is hidden]'. Did not match: validationParameters.ValidAudience: '[PII is hidden]' or validationParameters.ValidAudiences: '[PII is hidden]'.
at Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable`1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateAudience(IEnumerable`1 audiences, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: Bearer was not authenticated. Failure message: IDX10214: Audience validation failed. Audiences: '[PII is hidden]'. Did not match: validationParameters.ValidAudience: '[PII is hidden]' or validationParameters.ValidAudiences: '[PII is hidden]'.
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executing endpoint 'TRS.BookingService.Api.Controllers.BookingsController.Get (TRS.BookingService.Api)'
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Get", controller = "Bookings"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.ActionResult`1[System.Collections.Generic.IEnumerable`1[System.String]]] Get() on controller TRS.BookingService.Api.Controllers.BookingsController (TRS.BookingService.Api).
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method TRS.BookingService.Api.Controllers.BookingsController.Get (TRS.BookingService.Api) - Validation state: Valid
TRS.BookingService.Api.Controllers.BookingsController:Information: Getting all bookings
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action method TRS.BookingService.Api.Controllers.BookingsController.Get (TRS.BookingService.Api), returned result Microsoft.AspNetCore.Mvc.ObjectResult in 96.2159ms.
Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor:Information: Executing ObjectResult, writing value of type 'System.String[]'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action TRS.BookingService.Api.Controllers.BookingsController.Get (TRS.BookingService.Api) in 280.2344ms
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint 'TRS.BookingService.Api.Controllers.BookingsController.Get (TRS.BookingService.Api)'
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 1345.3829ms 200 application/json; charset=utf-8
因此,即使抛出异常表明令牌未验证,仍然允许请求继续并执行并将响应发送回客户端。
这是 ConfigureServices 的样子:
services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Authority = "https://localhost:44392/";
options.Audience = "FAKE_SCOPE";
});
以及 Configure() 方法
app.UseAuthentication();
app.UseMvc();
这是 JWT 令牌的样子:
{
"nbf": 1562062882,
"exp": 1562066482,
"iss": "https://localhost:44392",
"aud": [
"https://localhost:44392/resources",
"bookingApi"
],
"client_id": "clientId",
"scope": [
"bookingApi"
]
}
这是调用 API 的客户端代码。
var idpUrl = "https://localhost:44392/";
var clientId = "clientId";
var clientSecret = "secret";
var scope = "bookingApi";
var accessToken = await GetAccessTokenAsync(new Uri(idpUrl), clientId, clientSecret, scope);
string content = await GetContent(new Uri("https://localhost:44360/v1/bookings"), accessToken);
我想我在授权方面遗漏了一些东西,我尝试了不同的方法
services.Authorization()
在 ConfigureServices() 方法中,但它没有帮助,我猜我写错了。
最好的问候
马格努斯
在花了一天时间弄清楚为什么它不起作用后,我决定 step-thru Microsoft 代码并在 AuthenticationMiddleware 中找到它。
public class 身份验证中间件
{
私人只读 RequestDelegate _next;
public AuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes)
{
if (next == null)
{
throw new ArgumentNullException(nameof(next));
}
if (schemes == null)
{
throw new ArgumentNullException(nameof(schemes));
}
_next = next;
Schemes = schemes;
}
public IAuthenticationSchemeProvider Schemes { get; set; }
public async Task Invoke(HttpContext context)
{
context.Features.Set<IAuthenticationFeature>(new AuthenticationFeature
{
OriginalPath = context.Request.Path,
OriginalPathBase = context.Request.PathBase
});
// Give any IAuthenticationRequestHandler schemes a chance to handle the request
var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
{
var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler;
if (handler != null && await handler.HandleRequestAsync())
{
return;
}
}
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
if (result?.Principal != null)
{
context.User = result.Principal;
}
}
await _next(context);
}
}
基本上发生的事情是结果上有一个失败属性,其中包含我的身份验证异常,但由于代码中没有检查它,它将继续请求管道中的下一个中间件.所以我基本上写了自己的 AuthenticationMiddleware 添加检查 Failure 是否有值然后 return 403.
var defaultAuthenticate = await _schemas.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
if (result?.Principal != null)
context.User = result.Principal;
if (result?.Failure != null)
throw new AuthorizationException(result.Failure.Message);
}
await _next(context);
}
catch (AuthorizationException ex) when (!context.Response.HasStarted)
{
_logger.LogWarning(ex, "Unauthorized access encountered.");
context.Response.Clear();
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
}
然而,除了我之外,这不是我要做的事情,所以如果有人知道我为什么需要这样做,我会很高兴提供信息。
我在遇到同样的问题后看到了这篇文章。在多次敲击头部之后,我发现在我的案例中,这是通过使用 services.AddMvcCore()(在我的案例中使用 .AddJsonFormatters().AddDataAnnotations())而不是 services.AddMvc() 引起的。只有使用 .AddMvcCore() 我才能得到 401 令牌验证失败。
似乎您需要在使用 .AddMvcCore 时将 .AddAuthorization() 添加到组合中,因为默认情况下不添加它。没有它,令牌验证失败,但请求管道继续很愉快。
我 运行 遇到了一个非常奇怪的问题,我猜我在我的设置中遗漏了一些东西。
我有一个由 IdentityServer4 保护的 WebAPI。它仅使用 Client_credentials。如果我写错了 ClientId och ClientSecret 用户未通过身份验证,我将无法连接到我的 WebAPI。但是,如果我写错了范围名称,请求仍会得到处理,并且我会收到响应,奇怪的是会抛出异常,但由于某种原因,它会被 .NET Core Framework 忽略。
这是我输出的一些调试信息 window。
Microsoft.AspNetCore.Hosting.Internal.WebHost:信息:请求开始 HTTP/1.1 GET https://localhost:44360/v1/bookings
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: Failed to validate the token.
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidAudienceException: IDX10214: Audience validation failed. Audiences: '[PII is hidden]'. Did not match: validationParameters.ValidAudience: '[PII is hidden]' or validationParameters.ValidAudiences: '[PII is hidden]'.
at Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable`1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateAudience(IEnumerable`1 audiences, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: Bearer was not authenticated. Failure message: IDX10214: Audience validation failed. Audiences: '[PII is hidden]'. Did not match: validationParameters.ValidAudience: '[PII is hidden]' or validationParameters.ValidAudiences: '[PII is hidden]'.
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executing endpoint 'TRS.BookingService.Api.Controllers.BookingsController.Get (TRS.BookingService.Api)'
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Get", controller = "Bookings"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.ActionResult`1[System.Collections.Generic.IEnumerable`1[System.String]]] Get() on controller TRS.BookingService.Api.Controllers.BookingsController (TRS.BookingService.Api).
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method TRS.BookingService.Api.Controllers.BookingsController.Get (TRS.BookingService.Api) - Validation state: Valid
TRS.BookingService.Api.Controllers.BookingsController:Information: Getting all bookings
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action method TRS.BookingService.Api.Controllers.BookingsController.Get (TRS.BookingService.Api), returned result Microsoft.AspNetCore.Mvc.ObjectResult in 96.2159ms.
Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor:Information: Executing ObjectResult, writing value of type 'System.String[]'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action TRS.BookingService.Api.Controllers.BookingsController.Get (TRS.BookingService.Api) in 280.2344ms
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint 'TRS.BookingService.Api.Controllers.BookingsController.Get (TRS.BookingService.Api)'
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 1345.3829ms 200 application/json; charset=utf-8
因此,即使抛出异常表明令牌未验证,仍然允许请求继续并执行并将响应发送回客户端。
这是 ConfigureServices 的样子:
services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Authority = "https://localhost:44392/";
options.Audience = "FAKE_SCOPE";
});
以及 Configure() 方法
app.UseAuthentication();
app.UseMvc();
这是 JWT 令牌的样子:
{
"nbf": 1562062882,
"exp": 1562066482,
"iss": "https://localhost:44392",
"aud": [
"https://localhost:44392/resources",
"bookingApi"
],
"client_id": "clientId",
"scope": [
"bookingApi"
]
}
这是调用 API 的客户端代码。
var idpUrl = "https://localhost:44392/";
var clientId = "clientId";
var clientSecret = "secret";
var scope = "bookingApi";
var accessToken = await GetAccessTokenAsync(new Uri(idpUrl), clientId, clientSecret, scope);
string content = await GetContent(new Uri("https://localhost:44360/v1/bookings"), accessToken);
我想我在授权方面遗漏了一些东西,我尝试了不同的方法
services.Authorization()
在 ConfigureServices() 方法中,但它没有帮助,我猜我写错了。
最好的问候 马格努斯
在花了一天时间弄清楚为什么它不起作用后,我决定 step-thru Microsoft 代码并在 AuthenticationMiddleware 中找到它。
public class 身份验证中间件 { 私人只读 RequestDelegate _next;
public AuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes)
{
if (next == null)
{
throw new ArgumentNullException(nameof(next));
}
if (schemes == null)
{
throw new ArgumentNullException(nameof(schemes));
}
_next = next;
Schemes = schemes;
}
public IAuthenticationSchemeProvider Schemes { get; set; }
public async Task Invoke(HttpContext context)
{
context.Features.Set<IAuthenticationFeature>(new AuthenticationFeature
{
OriginalPath = context.Request.Path,
OriginalPathBase = context.Request.PathBase
});
// Give any IAuthenticationRequestHandler schemes a chance to handle the request
var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
{
var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler;
if (handler != null && await handler.HandleRequestAsync())
{
return;
}
}
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
if (result?.Principal != null)
{
context.User = result.Principal;
}
}
await _next(context);
}
}
基本上发生的事情是结果上有一个失败属性,其中包含我的身份验证异常,但由于代码中没有检查它,它将继续请求管道中的下一个中间件.所以我基本上写了自己的 AuthenticationMiddleware 添加检查 Failure 是否有值然后 return 403.
var defaultAuthenticate = await _schemas.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
if (result?.Principal != null)
context.User = result.Principal;
if (result?.Failure != null)
throw new AuthorizationException(result.Failure.Message);
}
await _next(context);
}
catch (AuthorizationException ex) when (!context.Response.HasStarted)
{
_logger.LogWarning(ex, "Unauthorized access encountered.");
context.Response.Clear();
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
}
然而,除了我之外,这不是我要做的事情,所以如果有人知道我为什么需要这样做,我会很高兴提供信息。
我在遇到同样的问题后看到了这篇文章。在多次敲击头部之后,我发现在我的案例中,这是通过使用 services.AddMvcCore()(在我的案例中使用 .AddJsonFormatters().AddDataAnnotations())而不是 services.AddMvc() 引起的。只有使用 .AddMvcCore() 我才能得到 401 令牌验证失败。
似乎您需要在使用 .AddMvcCore 时将 .AddAuthorization() 添加到组合中,因为默认情况下不添加它。没有它,令牌验证失败,但请求管道继续很愉快。