在多个设备上刷新令牌

问题描述 投票:0回答:3

我有一个 Api 和一个移动客户端。我使用刷新令牌如下:

  1. 用户提供凭据,Api 返回访问令牌和刷新令牌。然后刷新令牌及其到期日期时间保存在数据库的用户表中。
  2. 客户端使用给定的访问令牌消耗一些受保护的资源。
  3. 访问令牌过期,因此客户端提供刷新令牌并获取新的令牌对。
  4. 不断重复步骤2和3。

问题: 假设用户有 2 个设备,A 和 B。他使用设备 A 成功登录,因此他获得了 2 个令牌,他很高兴。一旦用户从设备 B 登录,Api 就会向他发送一对新的令牌,这意味着新的刷新令牌将覆盖设备 A 已经给定的令牌。现在用户返回设备 A aaa,它就消失了(无效刷新)令牌!)所以他必须再次提供凭据,而我、用户和您都不想这样做。

建议: 我找到了两种解决问题的方法,但因为我对这个主题还很陌生,所以我看不出哪种是最佳实践:

方法A: 为每个用户保存多个刷新令牌,并保存设备标识符(仍然不知道在移动、浏览器和桌面客户端等不同客户端类型的情况下到底是什么!)但无论如何。在此方法中,当用户从设备 A 登录时,Api 会提供两个令牌。用户从设备 B 登录,Api 会传递新的令牌对。他回到设备 A,再次使用他的第一个令牌(仍然有效)。

方法B: 每个用户保留 1 个刷新令牌。当用户从设备 B 登录时,Api 会发回唯一的刷新令牌(只要用户提供有效的凭据,我就不应该关心设备,对吧?)

您能指出每种方法的优缺点吗?

refresh-token
3个回答
15
投票

方法 A 是处理此问题的正常方法。访问/刷新令牌不应该在不同的会话/设备之间共享。 每个人都应该得到自己的一双。当您使用

refresh_token

操作时,它应该只会使与该请求一起使用的刷新令牌过期,而不是任何不相关的令牌。

    


0
投票

每个用户数据库条目都有一个

refreshTokens

字段,它是一个

RefreshTokenObject
数组,格式如下:
{token: <tokenUUID>, creationDate: Date}

登录

每次用户登录时,都会将新的

RefreshTokenObject

连接到现有令牌对象列表。

令牌刷新

后端对

map

条目执行

RefreshTokenObjects
,用新令牌和创建日期替换找到的
RefreshTokenObject
,将新的刷新 + 访问令牌发送给用户。如果未找到令牌,服务器将返回 401,正文中带有
refresh token expired
,提示前端重新登录。

退出

每次注销发生时,前端都会将正文发布到 /api/login/signout

和正文

{ userId: <id>, refreshToken: <tokenUUID> }

。如果在列表中找到相应的令牌,后端将删除相应的令牌。 
注意:
 我选择如果没有找到refreshToken,后端不返回404;这是一种极其奇怪的情况,只会导致在最坏的情况下重新登录。
良好实践

由于许多数据库都有文档大小限制,因此您必须小心不断增长的数组。我实现了一个 clearOldTokens

函数,该函数在每次登录、注销或刷新时运行。它只是将所有现有令牌的

creationDate

 字段与当前时间进行比较,如果令牌过期,它将从用户的 
refreshTokenObjects
 数组中删除该令牌。
使用设备 ID 等来跟踪这一点更加明智;只是更多的工作。

假设访问令牌持续 5 分钟,刷新令牌持续 1 周。访问令牌过期后,您将检查数据库是否具有请求中包含的刷新令牌。 (您还可以清理过期的刷新令牌。我将刷新令牌存储在 MongoDB 中的一个数组中,因此在修改它时,我不妨清理它以缩短它,然后再将其放回数据库中。)

0
投票
如果一切顺利,我会生成新的访问

刷新令牌,以将刷新令牌的到期日期重置为下周(因此用户不必再次登录,除非他长时间不活动)。这意味着之前的刷新令牌不再有效/使用,需要删除。

只有发出请求的设备才会知道新的刷新令牌,并且很难将此更改传达给其他设备,因此方法 B 不起作用。 (我怀疑您是否可以发送通知来更改其他设备的 cookie(使用刷新令牌)。)

© www.soinside.com 2019 - 2024. All rights reserved.