如何保护刷新令牌?

时间:2019-04-03 02:56:58

标签: oauth-2.0 access-token refresh-token

我正在使用JWT对我的应用程序的用户进行身份验证。用户登录时,将获得访问令牌和刷新令牌。为了确保刷新令牌的安全,我不将其存储在客户端,而是使用其帐户将其保存在后端,因此不容易访问。但是,我对刷新令牌的安全性感到困惑,这是我在阅读有关如何使用刷新令牌的在线资源时所理解的逻辑:

  1. 验证
  2. 将访问令牌+刷新令牌存储在某个位置(在我的情况下,在前端访问令牌,在后端刷新令牌)
  3. 执行api请求时,请在api端验证访问令牌
  4. 如果访问令牌已过期,请使用刷新令牌来生成新的访问令牌+新的刷新令牌,然后将访问令牌发送回客户端
  5. 像以前一样存储令牌...并重复

我担心的安全问题是其他人(黑客)是否拥有访问令牌,并且他们使用该令牌向api发送请求,如果令牌已过期,则api将使用刷新令牌来获取新的访问令牌+新的刷新令牌,然后至少将访问令牌返回给黑客。

我读了this条文章约5-6次,我读了this条文章,以及有关该主题的其他一些文章,他们都说了

  

请确保安全保存刷新令牌,因为它的寿命很长,access_token的寿命很短,所以没什么大不了的

但是根据我上面描述的流程,访问令牌是否短暂并不重要,刷新令牌将用于获取新的访问令牌并永远具有访问权限。

有什么我想念的吗?如果黑客掌握了过期的访问令牌,则api如何知道谁在发送请求?仍然会使用刷新令牌发送一个新的令牌。我是否应该以某种方式验证谁发送了请求?


更新

因此,我的理解是,当请求新的访问令牌时,我需要发送刷新令牌,客户端ID和客户端密码。我遇到的问题是,像以前一样,黑客可以将请求发送到我的API服务器,服务器从黑客那里获取被劫持的访问令牌,它将看到该令牌已过期,因此它将发送刷新令牌以及客户端ID /客户端密钥(作为环境变量存储)到Auth API,并获取新的访问令牌/刷新令牌,这使我们又回到了同样的问题。


更新2

关于这个问题的一些有趣的问题:

  1. Why Does OAuth v2 Have Both Access and Refresh Tokens?
  2. https://security.stackexchange.com/questions/87119/how-secure-are-expiring-tokens-and-refresh-tokens

根据第二个问题和答案,似乎刷新令牌并不是维护访问权限的更安全的方法,只是更容易检测到黑客,因为auth / refresh令牌不断被请求并使其他令牌无效。问题是,只有两个用户同时尝试访问资源时,才会发生这种情况-如果只有黑客在给定时间段内处于活动状态,则他将无限制地访问原始用户数据,直到原始用户尝试使用该应用程序并访问受保护的资源

7 个答案:

答案 0 :(得分:1)

您不应将令牌存储在服务器上。客户端进行身份验证并获取令牌。您将令牌存储在浏览器中的cookie或localStorage中。每个请求都使用令牌授权。如果通过不带ssl的未加密通道发送它,则很容易被拦截。黑客获得令牌确实允许他们假冒用户。过期的令牌应允许重新认证,而无需再次重新输入用户凭据。过期的令牌应被忽略。

答案 1 :(得分:0)

在您链接的第二篇文章中,据说要刷新令牌,您必须发布刷新令牌 client_id client_secret,因此基本上,您在重新验证用户时刷新访问令牌。

  

要使用刷新令牌,请使用grant_type = refresh_token向服务的令牌端点发出POST请求,并包括刷新令牌和客户端凭据。

答案 2 :(得分:0)

如果要在服务器上存储刷新令牌,则服务器应在身份验证响应中包括安全会话cookie,以识别用户。通过使用HttpOnly标志设置cookie,可以防止攻击者提取安全的会话cookie。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies

该cookie不会是刷新令牌。这将是其他某种会话cookie。不向用户返回刷新令牌的应用程序流是单页应用程序流。

https://auth0.com/docs/flows/concepts/single-page-login-flow

在此流程中,令牌刷新是通过“静音身份验证”完成的。

https://auth0.com/docs/api-auth/tutorials/silent-authentication#initiate-a-silent-authentication-request

  

成功的身份验证响应如果用户已经在Auth0中拥有有效的会话,并且无需征求同意或其他提示。

因此,我们需要通过存储一些用户标识符来维护会话。

答案 3 :(得分:0)

将要使用的访问令牌和刷新令牌如下:

  1. 在用户登录时生成过期的访问和刷新令牌,并将其发送到前端应用(Android,IOS,Web应用)。
  2. 前端应用程序将刷新令牌安全地存储在其数据库中。
  3. 前端应用程序随每个请求发送访问令牌,JWT对其进行验证 无需访问数据库。
  4. 身份验证在定义的访问令牌时间内有效。
  5. 到期时,前端应用程序将刷新令牌发送到您的服务器, 另外,您可以使用JWT进行验证,并在数据库中进行检查 为了平等。
  6. 服务器生成新的访问令牌,等等。
  

PS:整个通信应通过HTTPS进行。

我基于上述逻辑实现了我的实现,访问令牌每30分钟过期一次,并刷新令牌(有效期为一年)。

通过数据库验证刷新令牌的另一件事是,您可以控制用户登录过程,并且可以限制能够使用同一帐户使用您的应用程序的设备数量。

只要用户再次发送登录请求,您只需要更新服务器上的刷新令牌即可。

答案 4 :(得分:0)

有一个很好的文档OAuth 2.0 for Browser-Based Apps,其中讨论了这些应用程序的最佳实践。

我会选择在客户端或服务器上保留令牌。混合使用它们(在服务器上保留刷新令牌,并在浏览器中访问令牌),就可以创建具有自己漏洞的协议。

如果浏览器应用程序仅需要访问令牌就可以访问其后端,则可以考虑将后端用作OAuth2客户端(接收身份验证代码),获取用户的身份,并发布cookie,该cookie将在浏览器和后端。这比交换,刷新和验证OAuth2令牌要容易得多。

如果您确实希望将浏览器应用程序保持为接收令牌的OAuth2客户端,则应使用PKCE extension(这样,保存在网络缓存和浏览器历史记录中的身份验证代码就不能用于获取令牌)并获取新的刷新令牌和每个新的访问令牌-看看chapter about refresh tokens

  

授权服务器不应向基于浏览器的应用程序发放刷新令牌。

     

如果授权服务器确实选择向基于浏览器的应用程序发行刷新令牌,则它必须发行新的刷新   每个访问令牌刷新响应的令牌。这样做   减轻了刷新令牌泄漏的风险,因为泄漏的刷新   如果攻击者和合法用户都可以检测到令牌   客户尝试使用相同的刷新令牌。

您的浏览器应用程序可以将其令牌保留在sessionStorage中,以免页面重新加载。

答案 5 :(得分:0)

基本上,在基于浏览器的应用程序中使用刷新令牌似乎是个坏主意。刷新令牌适用于可以将刷新令牌安全地存储在电话上的移动应用程序-手机具有某种安全存储机制,而浏览器则没有。

答案 6 :(得分:0)

刷新令牌的安全性取决于授权服务器如何实施标识客户端,刷新令牌的再生和刷新令牌的无效的策略。

根据安全策略(针对Web客户端),可以在请求新的访问令牌时使刷新令牌无效,并且授权服务器还会生成新的刷新令牌并将其返回给客户端。 https://tools.ietf.org/html/rfc6749#section-10.4

从这个问题中我可以感觉到,授权服务器和资源服务器被视为一个,但事实并非如此。授权服务器是一种生成访问令牌和/或刷新令牌的服务器,而资源服务器是一种具有客户端尝试获得访问权限的资源的服务器。此外,刷新令牌仅提供给授权服务器以获取新的访问令牌,而访问令牌则由客户端提供给资源服务器以获取对受保护资源的访问。