【问题标题】:Identityserver4/OpenId Connect, Hybrid mode, Token Refresh FailsIdentityserver4/OpenId Connect,混合模式,令牌刷新失败
【发布时间】:2017-08-20 12:40:21
【问题描述】:

我有一个 ASP.net Core MVC 站点,它使用 OpenId 连接到另一个使用 IdentityServer4 的 ASP.net Core 站点进行身份验证,该站点使用另一个 IdentityServer4 站点作为身份提供者。

在客户端,只有很少的页面,理论上可以使用很长时间,只需要 AJAX 调用。我不希望网站刷新访问令牌,这样用户就不会被强制登录,比如说第二天。

我设置了一个计时器,它调用 MVC 站点上的 WebAPI 方法来刷新令牌。

它适用于第一次刷新两次,但在第三次刷新时总是失败。

该方法返回一个用于外部 API 调用的 JWT。我可以按预期在第一次调用时看到此更新,并且它获得了新的过期时间戳。

在第三次调用中,tokenClient.RequestRefreshTokenAsync 失败,因为 refreshToken 为空。

    public async Task<IActionResult> RefreshToken()
    {
        var disco = await DiscoveryClient.GetAsync(_authenticationOptions.Value.Authority);

        if (disco.IsError)
            return BadRequest(disco.Error);

        var tokenClient = new TokenClient(disco.TokenEndpoint, _authenticationOptions.Value.ClientId, _authenticationOptions.Value.ClientSecret);
        var refreshToken = await HttpContext.Authentication.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken);
        var tokenResult = await tokenClient.RequestRefreshTokenAsync(refreshToken);

        if (tokenResult.IsError)
            return BadRequest(disco.Error);

        var old_id_token = await HttpContext.Authentication.GetTokenAsync(OpenIdConnectParameterNames.IdToken);
        var new_access_token = tokenResult.AccessToken;
        var new_refresh_token = tokenResult.RefreshToken;

        var tokens = new List<AuthenticationToken>();
        tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.IdToken, Value = old_id_token });
        tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.AccessToken, Value = new_access_token });
        tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.RefreshToken, Value = new_refresh_token });

        var expiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(tokenResult.ExpiresIn);
        tokens.Add(new AuthenticationToken { Name = "expires_at", Value = expiresAt.ToString("o", CultureInfo.InvariantCulture) });

        var info = await HttpContext.Authentication.GetAuthenticateInfoAsync("Cookies");
        info.Properties.StoreTokens(tokens);

        await HttpContext.Authentication.SignOutAsync("Cookies");
        await HttpContext.Authentication.SignInAsync("Cookies", info.Principal, info.Properties);

        return Ok(HttpContext.Authentication.GetTokenAsync("access_token").Result);
    }

我可以看到,Chrome 正在控制台中通知 set-cookie 标头被忽略,因为它超过了 4kb。

有什么建议吗?

【问题讨论】:

  • 4KB 是 大多数 浏览器中 cookie 的限制:browsercookielimits.squawky.net 如果您可以使有效负载更小,或将其拆分为多个 cookie,则可以保存它们.
  • 根据规范有建议,但我之前提供的链接是一个更实际的限制:ietf.org/rfc/rfc2965.txt 请参阅第 5.3 节关于限制。
  • 我的猜测是因为没有try / catch 或任何null 检查,所以您看到的是HTML 中的堆栈跟踪页面以响应此操作。
  • @BerinLoritsch:我不认为我对这些 cookie 有权力。它们都是由 OpenId/IdentityServer 中间件设置的。
  • @BerinLoritsch:我没有得到堆栈跟踪。 tokenResult.IsError 是真的,所以我应该得到一个 HTTP 400 错误请求。这不应该是真的;)

标签: c# asp.net-core-mvc openid-connect identityserver4


【解决方案1】:

知道了。

客户端 IdentityToken 已过期,并且由于该 api 方法不受 [Authorize] 属性的保护,因此它没有更新 + 将脚本更改为使用 iframe 而不是 AJAX 调用!

结案。

【讨论】:

    猜你喜欢
    • 2018-01-08
    • 2020-02-14
    • 2014-05-02
    • 2018-07-07
    • 2019-03-23
    • 2020-09-12
    • 2017-03-30
    • 2019-12-23
    • 2017-06-04
    相关资源
    最近更新 更多