使用 JWT 和刷新令牌对移动应用程序进行身份验证

Posted

技术标签:

【中文标题】使用 JWT 和刷新令牌对移动应用程序进行身份验证【英文标题】:Authenticating a mobile application with JWT and refresh tokens 【发布时间】:2016-02-15 10:13:56 【问题描述】:

目前,我开始对此大发雷霆。过去几天我做了一些研究,似乎我不太明白如何实现以下目标:

我目前正在使用作为客户端的移动应用程序在 Rails 中构建 API。移动应用程序可以是 iosandroid。现在我正在努力进行身份验证。客户端登录设备后,我发出一个短期过期的 JWT。因此,如果令牌过期,客户端需要重新登录,这在我的情况下是不可接受的用户体验。无论如何,我觉得我需要某种到期来防止令牌被盗后永远使用。

现在我想知道如何集成刷新令牌。如何确保用户只能使用已颁发给此确切设备的有效刷新令牌来获得新的访问令牌?还是我把事情复杂化了,分配一个可以在所有设备上使用的刷新令牌就可以了?

更新:我查看了支持密码授予流程的门卫 gem。但是门卫处理令牌的方式是,它将每个生成的访问令牌与相应的刷新令牌一起存储在数据库中。当令牌被撤销或刷新时,旧的访问令牌会失效——随着时间的推移,这将增长到一个巨大的数据库表。

此外,我更喜欢使用 JWT 作为令牌,因此我不必在数据库中存储刷新令牌以外的任何内容。以下过程是否安全?

    用户使用用户名/密码请求访问令牌 - 假设是设备名称。 服务器发出 JWT 并为当前设备创建一个刷新令牌。 服务器存储刷新令牌。 当访问令牌过期时,用户使用它的刷新令牌请求一个新的。 服务器验证刷新令牌并发出新的访问令牌。此外,刷新令牌会被替换为新令牌。

我的问题:用户可以在多个设备上登录,如何区分它们?

【问题讨论】:

【参考方案1】:

安全性始终是相对的,通过更多努力,我们可以让任何人滥用系统变得更加困难。承载令牌受 IO 限制(缓存/数据库调用),JWT 令牌受 CPU(加密/解密)限制。两者都足以解决常规服务领域的问题,除了我们在这里对移动设备采取的一件事。此处可以使用的一种方法是通过反向通道将令牌/刷新令牌发送到设备,而不是将其作为身份验证的一部分发送。似乎有些额外的工作,但在为移动设备发布和刷新令牌方面提供了更多的安全性。更多细节可以在这里找到http://sdhankar.com/2016/10/24/authentication-and-jwt-token-refresh-on-mobile-devices/

【讨论】:

Stack Overflow 有一个 policy on affiliation disclosure 我知道您的网站与您的用户名匹配,但我建议您明确连接。例如,您可以在链接旁边添加短语“我的网站”。【参考方案2】:

我喜欢刷新令牌的想法。在后端使用doorkeeper gem 怎么样?这样,令牌到期就会在每个客户端请求时更新。

用户使用用户名/密码请求访问令牌,并且 - 比方说 设备名称。

向您的服务器发送用户名/密码和设备名称会破坏客户端不必向您提供凭据的目的。

我看到它是因为移动客户端向 oauth 提供者请求了一个令牌 ID(您需要一个服务器客户端 ID)。移动客户端将令牌 ID 发送到您的服务器进行验证,从而确保客户端的身份。服务器可以在成功验证提供的 JWT 中找到用户的电子邮件地址。请参阅 rails google-token-id gem。

【讨论】:

请查看我更新的问题。我想使用 JWT,而使用 doorkeeper + jwt 最终会将 jwt 令牌存储在数据库中 - 无论如何,JWT 应该是独立于数据库的,因此将它们存储在数据库中是没有意义的。【参考方案3】:

我看到这项工作的方式是服务器返回一个未经授权的状态 (401) 并带有一条指示访问令牌已过期的消息,但随后客户端恰好有一次机会请求一个已过期的新令牌令牌。一旦客户端使用该过期令牌请求新令牌,过期令牌将变为无效并且不能再使用。这样您就可以继续用旧代币换取新代币。

如果您的过期时间很短,被盗令牌仍然有效的可能性非常小,但从用户体验的角度来看,用户将保持登录状态,因为令牌协商可以在后台进行。仅当用户注销或他们使用的令牌在服务器端显式无效时,用户的令牌才会失效。

对于您拥有的每个用户名/密码组合,您绝对应该拥有一个唯一的令牌。为您的应用中的每个客户端使用相同的令牌会非常不安全。

【讨论】:

实际上我不太喜欢只有一个访问令牌而没有刷新令牌的想法。因此,潜在的攻击者可以使用被盗的访问令牌生成无限的新令牌。此外,我希望尽可能接近 OAuth2 规范。

以上是关于使用 JWT 和刷新令牌对移动应用程序进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章

同时从移动设备和 Web 刷新 JWT 令牌的最佳实践

我是不是正确理解用于身份验证的访问和刷新令牌技术?

JWT 身份验证方案中的刷新令牌是不是应该使用与访问令牌不同的秘密进行签名?

通过安全令牌进行 API 身份验证的最佳实践(Node.js 服务器和移动应用程序)

使用 JWT 的移动身份验证

Django REST JWT 刷新