如何在Oauth2中撤销RefreshToken并同时使AccessToken无效
本文关键字:无效 AccessToken RefreshToken Oauth2 | 更新日期: 2023-09-27 18:24:56
我正在使用Owin-Outh2开发单页应用程序(AngularJS+.Net MVC Json Rest API)的身份验证流(授权和资源服务器相同)。
我选择Bearer Token路由而不是传统的cookie+会话,因为我想保持无状态,也因为相同的Api将被移动应用程序使用,其中令牌的问题比cookie小。
这是简化的流程:
- 用户向服务器提交用户名/密码(通过HTTPS向TokenProvider路由)
- Owin创建一个
AccessToken
,声明包含生成的GUID(将表示类似会话Id的东西)和一些其他声明 - Owin创建了一个
RefreshToken
- 服务器在
RefreshToken
表中创建一个包含以下字段的条目:
GUID(PK)|RefreshToken|Ticket|DateIssue|DateExpire|DateEnd
-
服务器同时提供
AccessToken
和CCD_ 5发送给客户端。 -
客户端将
AccessToken
和RefreshToken
都存储到SessionStorage中。 -
客户端使用
AccessToken
访问API。
AngularJS检测到AccessToken即将过期时,缓冲所有请求并发出grant_type refresh_token request
服务器使用客户端提供的RefreshToken
和:
- 检查Db中的刷新令牌是否仍然有效(
DateExpire > GetTime() And DateEnd is Null
) - 从Db获取票证
- 从票证创建访问令牌
- 使用新的日期、新的
RefreshToken
和新的Ticket更新DB条目(注意:GUID保持不变)
当客户端访问注销服务器端时,从已登录用户的身份声明中读取的GUID用于使表上的条目无效(DateEnd = GetTime()
)
客户端的两个令牌都从SessionStorage
中移除。
通过这种方式,我可以撤销拒绝任何其他请求以获得新的AccessToken
的RefreshToken
。
这种方法的问题是,当授权被撤销时(即:RefreshToken
在DB上无效)存在一个时间窗口,但AccessToken
仍然有效(尽管时间帧有限)。
我想做的是在每个请求上检查AccessToken
的有效性,从用户身份声明中获取GUID,并点击数据库来检查该特定GUID的刷新令牌是否仍然有效。
尽管使查询执行O(1)非常简单,但单点故障本身可能会对系统的可扩展性和性能产生负面影响。
你知道缓解这个问题的另一种方法吗?你认为我的方法有什么缺陷吗?
您的方法没有错,与我之前在博客中提到的方法完全相同,但我建议在发送访问令牌时不要进行任何DB检查。
为什么不发布短时间访问令牌,即(30分钟),并且在撤销刷新令牌后等待访问令牌生存期到期。在客户端上,您可以从客户端的本地存储中清除刷新令牌和访问令牌。