JWT刷新令牌流

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

最好的方法似乎是将JWT访问令牌与刷新令牌配对,这样我就可以随心所欲地频繁地使访问令牌过期。

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

假设这是关于OAuth 2.0的,因为它是关于jwt和刷新令牌的…:

  1. 就像访问令牌一样,原则上,刷新令牌可以是包括您所描述的所有选项的任何东西;当授权服务器想要无状态或想要对呈现它的客户端强制某种“所有权证明”语义时,可以使用JWT;请注意,刷新令牌与访问令牌的不同之处在于,它不呈现给资源服务器,而只呈现给最初发布它的授权服务器,因此jwt -as-access-令牌的自包含验证优化不适用于刷新令牌

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

  3. 授权服务器可以同时发出访问令牌和刷新令牌,这取决于客户端用于获取它们的授权;该规范包含了每个标准化赠款的细节和选项

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

  1. 在这种情况下,他们使用一个uid,而不是JWT。当他们刷新令牌时,他们发送刷新令牌和用户。如果您将其实现为JWT,则不需要将其发送给用户,因为它将在JWT中。

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

  3. 在这个实现中,它同时响应登录方法,访问令牌和刷新令牌。在我看来这是正确的。

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

  1. 当您登录时,向客户端发送2个令牌(Access令牌,Refresh令牌)作为响应。
  2. 访问令牌的过期时间较短,而Refresh的过期时间较长。
  3. 客户端(前端)将刷新令牌存储在本地存储中,访问令牌存储在cookie中。
  4. 客户端将使用一个访问令牌来调用api。但是当它过期时,您调用认证服务器API来获得新的令牌(刷新令牌自动添加到http请求中,因为它存储在cookie中)。
  5. 您的认证服务器将公开一个API,该API将接受刷新令牌并检查其有效性并返回一个新的访问令牌。
  6. 一旦刷新令牌过期,用户将被注销。

如果你需要更多细节,请告诉我,我也可以分享代码(Java + Spring引导)。

关于你的问题:

Q1:这是另一款索赔较少、有效期较长的JWT。

问题2:它不会在数据库中。后端不会存储在任何地方。他们只会用私钥/公钥解密令牌,并用到期时间验证它。

Q3:是的,正确

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

  +--------+                                           +---------------+
|        |--(A)------- Authorization Grant --------->|               |
|        |                                           |               |
|        |<-(B)----------- Access Token -------------|               |
|        |               & Refresh Token             |               |
|        |                                           |               |
|        |                            +----------+   |               |
|        |--(C)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(D)- Protected Resource --| Resource |   | Authorization |
| Client |                            |  Server  |   |     Server    |
|        |--(E)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(F)- Invalid Token Error -|          |   |               |
|        |                            +----------+   |               |
|        |                                           |               |
|        |--(G)----------- Refresh Token ----------->|               |
|        |                                           |               |
|        |<-(H)----------- Access Token -------------|               |
+--------+           & Optional Refresh Token        +---------------+
  

  

(A)  The client requests an access token by authenticating with the
authorization server and presenting an authorization grant.
  

(B)  The authorization server authenticates the client and validates
the authorization grant, and if valid, issues an access token
and a refresh token.
  

(C)  The client makes a protected resource request to the resource
server by presenting the access token.
  

(D)  The resource server validates the access token, and if valid,
serves the request.
  

(E)  Steps (C) and (D) repeat until the access token expires.  If the
client knows the access token expired, it skips to step (G);
otherwise, it makes another protected resource request.
  

(F)  Since the access token is invalid, the resource server returns
an invalid token error.
  

(G)  The client requests a new access token by authenticating with
the authorization server and presenting the refresh token.  The
client authentication requirements are based on the client type
and on the authorization server policies.
  

(H)  The authorization server authenticates the client and validates
the refresh token, and if valid, issues a new access token (and,
optionally, a new refresh token).

关于你的问题:

  1. 这是另一个JWT
  2. 刷新令牌必须存储在服务器端
  3. 是的

智威汤逊有两个问题:

  1. < p >糟糕的标准化

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

第一个问题可以通过使用你自己的JWT实现来解决:把你想要的任何东西放入JSON中,用AES加密——看——用它来进行身份验证(如果需要也可以用于授权:把角色放在JSON中)。

超级简约的JWT {"id" : "<id>"}

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

撤销问题的一个常见解决方案是使用refresh-token

以下是如何做到这一点:

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