升级 IdentityServer4 到 Core 3.1 后,令牌突然未被正确签名?

3
我们在升级IdentityServer4(2.5.3 - 3.1.0)至Core 3.1(从2.2)时遇到了一个错误。突然之间,发行的令牌没有正确的签名。我们没有更改签名算法;在版本之间仍然使用相同的.PFX证书。
var idSrvBuilder = services.AddIdentityServer(opts =>
            {
                opts.Events.RaiseErrorEvents = true;
                opts.Events.RaiseFailureEvents = true;
                opts.Events.RaiseInformationEvents = true;
                opts.Events.RaiseSuccessEvents = true;
                if (_env.IsProduction())
                {
                    opts.PublicOrigin = Configuration["Globals:IdentityURL"];
                }
            }).AddSigningCredential(new X509Certificate2(Configuration["Cert:Path"], Configuration["Cert:Password"]));

当为旧的API使用OWIN中间件 "UseIdentityServerBearerTokenAuthentication" 时,如果 ValidationModeLocal,它会失败,但如果直接对IdentityServer进行验证(ValidationModeValidationEndpoint),则不会失败。该API只会返回 "未经授权",但使用旧令牌(签名相同的证书!)可以正常工作。

app.UseIdentityServerBearerTokenAuthentication(new IdentityServer3.AccessTokenValidation.IdentityServerBearerTokenAuthenticationOptions
            {
                Authority = AppSettings.Authority,
                ClientId = AppSettings.ApiName,
                ClientSecret = AppSettings.ApiSecret,
                EnableValidationResultCache = false,
                ValidationMode = IdentityServer3.AccessTokenValidation.ValidationMode.Local
            });

针对不同版本之间发行的令牌,有一个显著的区别:

旧版(已删除有效载荷):

eyJhbGciOiJSUzI1NiIsImtpZCI6IjZCMTM4RUIzMUE4OUExQTdEQTdCNkRGNzMwOTRGMzIzREJFNzhCNjYiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJheE9Pc3hxSm9hZmFlMjMzTUpUekk5dm5pMlkifQ.U3unxhW6act8fQLCLAYBJAZ-lIMiKaghVEUdA3b7iM0mI0UqGmYgYw05SvVXTAT8ZNQPuq0D-97d0Z6VVBC2wH7VAl0daF6sYJyuSUEtDiBPttNQ9MsGBNjcN1HABZ0nv-z_lgG2Z9sgp4blCvc7N8xOsja-kuk6m06I7iOfS7O_YKPtTAXA10OCzdtiJbhYijeTFsBJaWf5-J3XJCtqpp-MGXCboE0gQIlvysKz5_CRaaKYptczw-cTX3sgRIhfWn2VxVujhH7JKeSJan52X-fQ4T47PWuVcWNOrcWheeLAbVDQU1U9DiLVVua3BasnIku5Rx4XcLnqCaokCiWZhg

使用以下令牌头:

{
  "alg": "RS256",
  "kid": "6B138EB31A89A1A7DA7B6DF73094F323DBE78B66",
  "typ": "JWT",
  "x5t": "axOOsxqJoafae233MJTzI9vni2Y"
}

新功能:

eyJhbGciOiJSUzI1NiIsImtpZCI6IjZCMTM4RUIzMUE4OUExQTdEQTdCNkRGNzMwOTRGMzIzREJFNzhCNjYiLCJ0eXAiOiJhdCtqd3QiLCJ4NXQiOiJheE9Pc3hxSm9hZmFlMjMzTUpUekk5dm5pMlkifQ.RmKHRk44c6Ele-VbB8lhNsmmcvKFludaWypuBzQzYqR7AEIuLXAuZ-N4I9ooVvQLHisBJT4qA4epEK9xdtf0ELpcvfEe3Yc2dkJnKp_rjJSRuhqyNHD0hPAoxqVSWHhfaLxLiL7_17mklqLDEqwdXANnA2YCO-Q-9wqGALZorywHYucr0X9m2hYm1oVgXPitG_TAqysYVNnLCHVGZRNE7Xmug0XhkJXzQ8RpZuSHlDHFlT2cgb7psEb4NUfA8v5-q-LyqfPDk4xJZX2ia53SoPpiJbByFgscYF4xk54SkkcB9EOxCCsR-IYHJAmyYkhGRpBVWY5xU_9qb2ioIwkzZg

使用以下标题:
{
  "alg": "RS256",
  "kid": "6B138EB31A89A1A7DA7B6DF73094F323DBE78B66",
  "typ": "at+jwt",
  "x5t": "axOOsxqJoafae233MJTzI9vni2Y"
}

我猜问题出在新令牌中的"typ""at+jwt"?这是什么意思?我已经查看了IdentityServers的发布、Github问题、谷歌搜索和StackOverflow,但似乎没有人注意到神秘的新"at+jwt" "typ"
这可能导致问题吗?我如何指示我的新版本发出标准JWT?这个奇怪的at+jwt是什么?

1
这被称为显式类型。您可以通过使用IdentityServer选项来覆盖该值以禁用此行为。 - user4864425
1
谢谢!似乎已经解决了这个问题。 - HenrikM
1
此外,刚刚发现了这个问题 - user4864425
1个回答

2

感谢评论中的@Ruard van Elburg提供了显式类型令牌的链接。

将默认的“at+jwt”更改为“jwt”解决了这个问题:

var idSrvBuilder = services.AddIdentityServer(opts =>
            {
                opts.Events.RaiseErrorEvents = true;
                opts.Events.RaiseFailureEvents = true;
                opts.Events.RaiseInformationEvents = true;
                opts.Events.RaiseSuccessEvents = true;
                opts.AccessTokenJwtType = "jwt";
                if (_env.IsProduction())
                {
                    opts.PublicOrigin = Configuration["Globals:IdentityURL"];
                }
            });

我猜测问题的根源在于我们在该API中使用的包IdentityServer3.AccessTokenValidation无法识别at+jwt。我们使用它来潜在地支持引用令牌。
由于需要支持第三方依赖项,我们也无法将此API升级到ASP Core并使用Microsoft的新版IdentityServerAuthenticationExtensions。该软件包似乎可以很好地处理at+jwt
编辑:
仍然没有起作用。查看了Ruard链接到的Github问题。
结果我还必须打开EmitLegacyResourceAudienceClaim,现在它看起来像这样:
var idSrvBuilder = services.AddIdentityServer(opts =>
            {
                opts.Events.RaiseErrorEvents = true;
                opts.Events.RaiseFailureEvents = true;
                opts.Events.RaiseInformationEvents = true;
                opts.Events.RaiseSuccessEvents = true;
                opts.AccessTokenJwtType = "JWT";
                opts.EmitLegacyResourceAudienceClaim = true;
                if (_env.IsProduction())
                {
                    opts.PublicOrigin = Configuration["Globals:IdentityURL"];
                }
            })

1
实际上,我怀疑问题出在更深的一层。AccessTokenValidation包调用了JwtFormat,但没有指定类型。然后JwtFormat为验证设置了AuthenticationType参数_validationParameters.AuthenticationType = "JWT"; - user4864425
似乎这并没有解决问题。我忘记将ValidationMode更改为“Local”或“Both”,立即出现“此请求的授权已被拒绝”。尝试更改签名密钥,也没有起作用。 - HenrikM
在我的情况下,这个解决方案起作用了!非常感谢!这个能被标记为答案吗? - Ravior
1
现在IdentityServer4更改为EmitStaticAudienceClaim而不是EmitLegacyResourceAudienceClaim。 - Nguyen Tran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接