IdentityServer4 参考访问令牌有时作为 JWT 令牌传输

Posted

技术标签:

【中文标题】IdentityServer4 参考访问令牌有时作为 JWT 令牌传输【英文标题】:IdentityServer4 Reference Access Token Sometimes being transmitted as JWT Token instead 【发布时间】:2021-12-02 14:24:43 【问题描述】:

我们刚刚将 Web 应用程序升级到 .NET 5,将 IdentityServer4 升级到 V4,我们也从混合流切换到代码 + PKCE。客户端设置为访问令牌类型的引用,客户端也将不记名令牌用于内部 API 以及用于主网站的 cookie。

当我们随机部署到内部开发服务器 (IIS 8.5) 或 Azure 应用服务时,当我们请求访问令牌(参考)时,我们会返回一个访问令牌 (JWT)。我们确实使用了 httpContext.GetTokenAsync() 方法,但随后将其替换为 identitymodel.aspnetcore GetUserAccessTokenAsync() 方法,但它仍然返回 JWT Token。

我已验证 JWT 令牌内容,它们是相关用户及其声明。我还检查了持久授权表,其中输入的参考令牌将其指定为 JWT 而不是参考。

纠正这种情况的唯一方法是

    停止网站和身份服务器 清除浏览器中的cookies 删除持久授权表中的所有条目 回收应用程序池 启动身份服务器,然后执行登录 启动登录的网站,突然我们又得到一个参考访问令牌

身份服务器客户端配置

                AllowedGrantTypes = 
                
                    GrantType.AuthorizationCode,
                    "exchange_reference_token"
                ,
                AccessTokenType = AccessTokenType.Reference,
                AccessTokenLifetime = 86400,

                RequireConsent = false,
                AllowAccessTokensViaBrowser = true,

                ClientSecrets =
                
                    new Secret("*******)
                ,

                RedirectUris =  $"client/signin-oidc" ,
                PostLogoutRedirectUris =  $"client/signout-callback-oidc" ,
                FrontChannelLogoutUri = $"client/signout-oidc",

                AllowedCorsOrigins =  client ,

                AllowedScopes =
                
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    "roles",
                    "API1",
                    "API2",
                    "API3",
                    "Signalr"
                ,
                UpdateAccessTokenClaimsOnRefresh = true,
                AllowOfflineAccess = true

【问题讨论】:

【参考方案1】:

我找到了导致问题的原因。我们在网站中使用信号器,我们必须使用 exchange_reference_token,但是在交换代码中它强制访问令牌到 JWT,然后将其插入持久授权表中,导致任何未来请求返回 JWT 而不是引用访问令牌

public async Task ValidateAsync(ExtensionGrantValidationContext context)

    var referenceToken = context.Request.Raw.Get("token");

    if (referenceToken == null)
    
        context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Missing Reference Token");
    

    var result = await _validator.ValidateAccessTokenAsync(referenceToken);
    if (result == null)
    
        context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid Reference Token");
    

    // Generate the JWT as if it was for the reference token's client           
    context.Request.Client.AccessTokenType = AccessTokenType.Jwt;

    var sub = result.Claims.FirstOrDefault(c => c.Type == "sub").Value;

    context.Result = new GrantValidationResult(sub, GrantType, result.Claims);

【讨论】:

以上是关于IdentityServer4 参考访问令牌有时作为 JWT 令牌传输的主要内容,如果未能解决你的问题,请参考以下文章

IdentityServer4 访问令牌生命周期

如何通过方法(不是api)通过identityserver4获取访问令牌?

刷新 IdentityServer4 客户端中的访问令牌

如何通过自省验证 IdentityServer4 访问令牌

如何在 IdentityServer4 中添加自定义声明以访问令牌? [关闭]

如何使用 IdentityServer4 访问令牌和 [Authorize] 属性