我的 ASP.NET Core REST API 使用 2 个身份验证中间件 - JWT 来验证用户(由 ADFS 颁发的令牌),以及 IdentityServer 来验证来自其他服务的调用。这些中间件的配置如下所示:
智威汤逊
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new X509SecurityKey(federationMetadata.GetSigningCertificate()),
ValidateIssuer = true,
ValidIssuer = federationMetadata.GetIssuerUri().AbsoluteUri,
ValidateAudience = true,
ValidAudience = validAudience,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
TokenValidationParameters = tokenValidationParameters
});
身份服务器 4 (IDS)
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = dbConfig.IdentityServer.AbsoluteUri,
ScopeName = Configuration.ServiceName,
RequireHttpsMetadata = false
}
我在使用此设置时遇到问题:
当用户从 ADFS 传递令牌时,JWT 中间件会成功验证令牌。然后 IDS 中间件无法验证令牌并引发错误:
IDX10503: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.RsaSecurityKey , KeyId: <MyRsaKey>
这是意料之中的。如果较早的中间件已成功验证请求,我如何告诉 IDS 中间件不进行验证?
我已经尝试了几件事。在我看来,理想的做法是解决OnMessageReceived
用户已通过身份验证的 IDS 事件,并告诉 IDS 中间件不要做进一步检查:
JwtBearerEvents = new JwtBearerEvents()
{
OnMessageReceived = async (context) =>
{
if(UserIsAlreadyAuthenticated)
DoNothingMore();
}
}
- 我如何测试用户是否经过身份验证?
- 如何告诉中间件接受身份验证并且不再进行处理?
我尝试过捕获 IDSOnAuthenticationFailed
事件并跳过中间件:
OnAuthenticationFailed = async (context) =>
{
if (context.Exception is IdentityServerNotAvailableException)
{
context.SkipToNextMiddleware();
}
}
但然后我得到一个范围验证失败:
Scope validation failed. Return 403.
范围验证在哪里进行?因为似乎 IDS 中间件中的任何错误都会导致范围验证错误,无论我是否SkipToNextMiddleware
。
如果我删除 IDS 中间件,一切正常。
谢谢你的帮助!
编辑:我现在已经解决了范围验证问题。我尝试ValidateScope = false
在 IDS 中间件上设置选项,但这会导致中间件内部出现空引用异常;但我发现如果我注释掉该ScopeName = Configuration.ServiceName
选项,范围验证问题就解决了(我在自定义处理程序中处理它 - 不理想)。
仍然需要知道:如果令牌已成功通过身份验证,如何告诉 IdentityServer 中间件跳过,或者在OnMessageReceived
事件中识别成功的先前身份验证,以便我可以自己调用SkipToNextMiddleware()
那里。
谢谢!