JWT刷新令牌流

jtm*_*mon 87 security authentication oauth-2.0 jwt

我正在构建一个移动应用程序,并使用JWT进行身份验证.

看起来最好的方法是将JWT访问令牌与刷新令牌配对,这样我就可以根据需要随时使访问令牌过期.

  1. 刷新令牌是什么样的?它是随机字符串吗?这个字符串加密了吗?这是另一个JWT吗?
  2. 刷新令牌将存储在用户模型的数据库中以供访问,对吗?看起来它应该在这种情况下加密
  3. 我会在用户登录后发回刷新令牌,然后让客户端访问一个单独的路径来检索访问令牌吗?

Den*_*sel 57

OAuth 2.0 规范文档中描述了刷新令牌流程。

\n
  +--------+                                           +---------------+\n  |        |--(A)------- Authorization Grant --------->|               |\n  |        |                                           |               |\n  |        |<-(B)----------- Access Token -------------|               |\n  |        |               & Refresh Token             |               |\n  |        |                                           |               |\n  |        |                            +----------+   |               |\n  |        |--(C)---- Access Token ---->|          |   |               |\n  |        |                            |          |   |               |\n  |        |<-(D)- Protected Resource --| Resource |   | Authorization |\n  | Client |                            |  Server  |   |     Server    |\n  |        |--(E)---- Access Token ---->|          |   |               |\n  |        |                            |          |   |               |\n  |        |<-(F)- Invalid Token Error -|          |   |               |\n  |        |                            +----------+   |               |\n  |        |                                           |               |\n  |        |--(G)----------- Refresh Token ----------->|               |\n  |        |                                           |               |\n  |        |<-(H)----------- Access Token -------------|               |\n  +--------+           & Optional Refresh Token        +---------------+\n  \n  \n  (A)  The client requests an access token by authenticating with the\n       authorization server and presenting an authorization grant.\n  \n  (B)  The authorization server authenticates the client and validates\n       the authorization grant, and if valid, issues an access token\n       and a refresh token.\n  \n  (C)  The client makes a protected resource request to the resource\n       server by presenting the access token.\n  \n  (D)  The resource server validates the access token, and if valid,\n       serves the request.\n  \n  (E)  Steps (C) and (D) repeat until the access token expires.  If the\n       client knows the access token expired, it skips to step (G);\n       otherwise, it makes another protected resource request.\n  \n  (F)  Since the access token is invalid, the resource server returns\n       an invalid token error.\n  \n  (G)  The client requests a new access token by authenticating with\n       the authorization server and presenting the refresh token.  The\n       client authentication requirements are based on the client type\n       and on the authorization server policies.\n  \n  (H)  The authorization server authenticates the client and validates\n       the refresh token, and if valid, issues a new access token (and,\n       optionally, a new refresh token).\n
Run Code Online (Sandbox Code Playgroud)\n

关于您的问题:

\n
    \n
  1. 这是另一个智威汤逊
  2. \n
  3. 刷新令牌可以存储在client\xe2\x80\x98s端的后端,这样用户就无法访问它。否则必须对其进行加密。
  4. \n
  5. 登录后您将获得刷新令牌以及访问令牌。当您的访问令牌过期时,您可以将刷新令牌发送到服务器以获取新的刷新和访问令牌。
  6. \n
\n

  • 在资源服务器上同时处理访问令牌和刷新令牌有什么安全风险? (3认同)

Han*_* Z. 26

假设这是关于OAuth 2.0,因为它是关于JWT和刷新令牌......:

  1. 就像访问令牌一样,原则上刷新令牌可以包括你描述的所有选项; 当授权服务器想要无状态或者想要向呈现它的客户端强制执行某种"拥有证明"语义时,可以使用JWT; 请注意,刷新令牌与访问令牌的不同之处在于它不会呈现给资源服务器,而只会呈现给首先发布它的授权服务器,因此JWTs作为访问令牌的自包含验证优化确实如此.不适用于刷新令牌

  2. 这取决于数据库的安全性/访问权限; 如果数据库可以被其他方/服务器/应用程序/用户访问,那么是(但您的里程可能因存储加密密钥的位置和方式而异)...

  3. 授权服务器可以同时发出访问令牌和刷新令牌,具体取决于客户端获取它们的授权; 规范包含每个标准化拨款的详细信息和选项

  • 2.您应该在数据库中存储刷新令牌的哈希值,然后将用户刷新令牌的哈希值与存储的哈希值进行比较."不在您的数据库中存储纯文本密码"的规则如下所示.考虑为您为用户创建的随机密码等令牌. (12认同)
  • 另外,如果您想提供更多安全性,还可以执行刷新令牌轮换。其重要性已在 [ITEF RFC 6749](https://tools.ietf.org/html/rfc6749#page-47) 中提到。如果实施正确,这还可以帮助识别令牌盗窃场景,即刷新令牌被攻击者窃取。如果您正在寻找更好的解释,请访问此[链接](https://supertokens.io/blog/the-best-way-to-securely-manage-user-sessions?s=r) (8认同)
  • 我确实建议遵循[此链接](https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/)来保护前端的 JWT 令牌和刷新令牌。 (2认同)

Bhu*_*ngh 25

以下是撤销您的JWT访问令牌的步骤:

1)登录后,发送2个令牌(访问令牌,刷新令牌)作为对client的响应。
2)访问令牌的有效期将更少,而刷新将具有较长的到期时间。
3)客户端(前端)将刷新令牌存储在其本地存储中,并将访问令牌存储在cookie中。
4)客户端将使用访问令牌来调用api。但是,当它过期时,请从本地存储中选择刷新令牌,然后调用auth服务器api以获取新令牌。
5)您的身份验证服务器将公开一个api,它将接受刷新令牌并检查其有效性并返回新的访问令牌。
6)刷新令牌过期后,用户将注销。

如果您需要更多详细信息,请让我知道,我也可以共享代码(Java + Spring引导)。

对于您的问题:
队列1:这是另一个JWT,具有较少的索赔且到期时间较长。

队列2:它将不在数据库中。后端将不会存储在任何地方。他们将只使用私钥/公钥对令牌解密,并使用其到期时间对其进行验证。

Que3:是的,正确的

  • 我认为JWT应该存储在localStorage中,而refreshToken应该存储在httpOnly中。refreshToekn可以用来获取新的JWT,因此必须格外小心。 (10认同)
  • @JaiSharma-如果服务器存储了刷新令牌,那么当客户端没有刷新令牌时,客户端将如何请求新的访问令牌。现在我们是否需要另一个 api 来获取登录用户的刷新令牌?请澄清在这种情况下该过程将如何进行。 (7认同)
  • @Jay 根据 Microsoft Developer Network 的说法,HttpOnly 是 Set-Cookie HTTP 响应标头中包含的附加标志。在生成 cookie 时使用 HttpOnly 标志有助于降低客户端脚本访问受保护 cookie 的风险(如果浏览器支持)。 (6认同)
  • #2非常不准确。刷新令牌必须存储在服务器端。您不应该将JWT的“自包含”属性用于刷新令牌。这样做会使您除了更改私钥外无法撤消刷新令牌。 (4认同)
  • 攻击者不能从用户的计算机获取访问令牌和刷新令牌并使用它生成新的访问令牌来获得访问权限吗?这里的保护在哪里?!? (4认同)
  • 我缺少使用刷新令牌的好处,扩展访问令牌的有效性会有所不同吗? (3认同)
  • 如前所述,#2 绝对不是重点。 (3认同)
  • 如果后端不存储刷新令牌,它如何被撤销? (3认同)
  • 这个答案和评论中存在一些误解。1.(重要)**刷新和访问令牌都应存储在 cookie 中**(最好带有“HttpOnly”标志)。LocalStorage 不应用于敏感数据,2. 没有必要将两个令牌存储在后端数据库中(JWT 的主要优点之一是能够在不访问数据库的情况下进行身份验证。这可以减少数据库重叠)。但是,如果您不在数据库中存储刷新令牌,则使一个令牌无效的一种可能方法是更改​​密钥并使所有令牌无效(所有用户都将被注销)。例如 github 有时会做这个技巧 (3认同)
  • 没有必要在服务器端存储整个刷新令牌。例如,您可以使用 JWT 作为刷新令牌,并将其“jti”(https://www.rfc-editor.org/rfc/rfc7519#page-10)声明存储在服务器端。这样做的优点是您不会在服务器数据库中存储纯文本(刷新)令牌,但仍然可以创建已撤销令牌的阻止列表。 (3认同)
  • 谢谢,您存储在httpOnly中是什么意思?为什么不将两者都存储在localStorage中? (2认同)
  • @user2010955 访问令牌将由客户端在每个后续请求中发送,这意味着有人捕获的可能性很高。 (2认同)
  • 将刷新令牌存储为 cookie 的问题是,虽然它比本地存储更安全,但它也会在每个后续请求中通过线路发送,从而增加了刷新令牌被泄露的可能性。Auth0 建议仅当客户端应用程序上没有后端时才将刷新令牌存储在内存中,而不是将其存储在容易受到 XSS 攻击的本地存储中。https://auth0.com/docs/security/store-tokens#if-no-backend-is-present (2认同)
  • @VishnuDahatonde,vishnu-dahatonde,这是链接:https://github.com/BhupinderSingh03/microService (2认同)
  • 如果您使用像 React 这样的框架,它本身是防 xss 的,并且您可以安全地使用 localstorage 来保存任何令牌。其次,由于偏执,每当“/refreshtoken”时我都会重新创建刷新令牌,因此以前的刷新令牌变得无效。我还将最后发布的 JWT 与刷新令牌一起存储在数据库中,因此每当调用“/refresh”时,最后发布的 JWT 也应该存在,否则它是无效请求并且用户会被注销。 (2认同)

小智 21

基于此实现,使用JWT的Node.js和刷新令牌:

1)在这种情况下,他们使用uid,而不是JWT.当他们刷新令牌时,他们会发送刷新令牌和用户.如果将其实现为JWT,则无需发送用户,因为它将在JWT内部.

2)他们在一个单独的文件(表格)中实现这一点.这对我来说很有意义,因为用户可以登录不同的客户端应用程序,并且可以通过应用程序获得刷新令牌.如果用户丢失了安装了一个应用程序的设备,则该设备的刷新令牌可能会失效,而不会影响其他已登录的设备.

3)在此实现中,它使用访问令牌和刷新令牌响应登录方法.它对我来说是正确的.


yur*_*rin 5

JWT 有两个问题:

  1. 糟糕的标准化

  2. 很难撤销(用于身份验证时)

第一个可以通过使用您自己的 JWT 实现来解决:将您想要的任何内容放入 JSON,使用 AES 对其进行加密 - 瞧 - 将其用于身份验证(如果需要,也可用于授权:将角色放入 JSON 中)。

超简约智威汤逊{"id" : "<id>"}

第二个问题需要澄清。对于存储在服务器端的常规会话,不存在撤销问题:服务器可以随时使会话失效。但常规会话在可扩展性和性能方面存在问题,因此出现了 JWT。

撤销问题的常见解决方案是使用刷新令牌

具体方法如下:

  1. 刷新令牌可以是与访问令牌完全相同的 JWT :自定义 JSON 加密和 Base64 编码。结果字符串可以只是重复。如果访问令牌包含大量数据(例如角色),则刷新令牌可能会有所不同,因为它只需要用户 ID。访问令牌刷新令牌内部都没有任何硬编码的过期时间。
  2. 它们都存储在https_only cookie 中,但访问令牌cookie的过期时间为2 分钟,刷新令牌cookie 的过期时间为30 分钟
  3. 刷新令牌存储在数据库(用户表)中,可以通过从数据库中删除来轻松撤销/失效。
  4. 服务器在请求中查找访问令牌:如果存在且有效(可以解密)-确定处理请求;
  5. 如果访问令牌不存在(cookie 过期),服务器会查找刷新令牌:如果存在 - 通过将其与数据库中存储的访问令牌进行比较进行验证,并生成新的访问令牌(基于刷新令牌中的信息)和 DB)并处理请求。
  6. 如果刷新令牌不存在,则服务器会查找以下其中一项:用户名密码对、第三方身份提供商令牌(Google、Facebook 等)、第三方身份管理系统令牌(Cognito、Okta) 、跳云)。如果找到任何:处理请求并生成新的访问和刷新令牌
  7. 如果找不到任何内容,则服务器会发送身份验证错误并强制客户端重新登录用户。