带有存储在 cookie 中的刷新令牌的 SPA - 如何使用 IdentityServer4 进行配置?

Posted

技术标签:

【中文标题】带有存储在 cookie 中的刷新令牌的 SPA - 如何使用 IdentityServer4 进行配置?【英文标题】:SPA with refresh tokens stored in cookie - how to configure with IdentityServer4? 【发布时间】:2020-07-02 21:31:32 【问题描述】:

我有一个 SPA,它使用长寿命的自包含 JWT 与 API 进行通信以进行身份​​验证。

SPA 当前正在将此 JWT 存储在本地存储中。

除了从安全角度来看这非常糟糕之外,另一个主要问题是我有办法撤销对 API 的访问(顺便说一句,需要保持无状态)。一个用户拥有一个令牌,他们可以无限期地使用它。

我想开始使用刷新令牌。我知道这些通常不推荐用于 SPA,但是在阅读 The Ultimate Guide to handling JWTs on frontend clients 之后,我相信有一种方法可以安全地做到这一点。

我想要什么:

当用户登录(密码授予)时,服务器仅响应一个短暂的 access_token,但使用刷新令牌设置一个 HttpOnly cookie。 客户端将 access_token 存储在内存中,并在发出 API 请求时使用。 当 access_token 即将到期时,我会向身份验证服务器发出请求以刷新令牌。因为 cookie 是由身份验证服务器设置的,所以它会自动包含在请求中。服务器以我们存储在内存中的更新后的 access_token 进行响应。 如果用户离开 SPA 并稍后返回,我们可以简单地向身份验证服务器发出请求以刷新令牌,这为我们提供了一个全新的令牌(无需在本地存储中存储任何内容)。李>

这似乎是最安全的选择,最小化 XRSF 和 CSRF:

如果有人设法将一些代码注入 SPA 并窃取了 access_token,它无论如何都会在 5 分钟后过期。注入的代码永远无法访问 refresh_token。 您无法欺骗用户发出 CSRF API 请求,因为您没有 access_token(访问令牌有效地用作 CSRF 令牌)。 如果有人确实设法获得了对 refresh_token 的访问权限,则可以在身份验证服务器上撤销它。

如果这个方法和我想的一样充分证明(请证明我错了!),为什么网上很少提到它?

IdentityServer4 文档似乎没有涵盖这一点。有人可以建议如何实施吗?我希望我可以在客户端配置中按照UseCookiesForRefresh 的行设置一个属性,但没有。

【问题讨论】:

您是否设法使用 RefreshToken 刷新 AccessTokens?请问您如何保护刷新过程中需要的 Spa 中的 client_secret? 【参考方案1】:

您可以在用户会话结束(或注销)时使用 ReferenceToken 类型而不是 Jwt Token 来撤销令牌。 Reference Token

您需要在客户端配置中更改 AccessTokenType

new Client
    
        ClientName = "OAuth Test",
        ClientId = "TestClientId",
        AllowedGrantTypes = GrantTypes.Hybrid,
        AccessTokenLifetime = 300,
        AllowOfflineAccess = true,
        AccessTokenType = AccessTokenType.Reference,
        ......
    

当用户注销时,您可以使用以下几行来撤销该会话中生成的所有令牌。

await _interaction.RevokeTokensForCurrentSessionAsync();

【讨论】:

以上是关于带有存储在 cookie 中的刷新令牌的 SPA - 如何使用 IdentityServer4 进行配置?的主要内容,如果未能解决你的问题,请参考以下文章

存储在 cookie 中的 JWT - 安全问题

SPA中令牌存储和刷新的选项

带有 JWT 的 AngularJS 或 SPA - 到期和刷新

为啥刷新令牌对于 SPA 来说被认为是不安全的?

IdentityServer4 - 刷新令牌混合流程 - Cookie 和存储

在 AngularJS SPA 中使用刷新令牌