OAuth 2.0 刷新令牌多个选项卡
Posted
技术标签:
【中文标题】OAuth 2.0 刷新令牌多个选项卡【英文标题】:OAuth 2.0 Refresh Token multiple Tabs 【发布时间】:2020-09-01 00:42:44 【问题描述】:在使用 OAuth 2.0 JWT 刷新令牌实现时,我遇到了一个问题,即在 Web 浏览器客户端上实现可靠的刷新策略确实很困难。多个选项卡可能会导致请求出现竞争状态。
RFC 没有明确提到服务器端的刷新令牌仅对一个(第一个)请求有效,但我认为在使用刷新令牌时使其无效是个好主意。
堆栈溢出问题已经有多种“解决方案”,但似乎没有一个是直截了当的。
一种解决方案是在请求中添加 Jitter 并通过本地存储同步请求。
如果我理解正确,您会在请求启动时将变量放入本地存储,其他选项卡检查是否设置了此变量,然后不启动刷新?你知道这个的示例实现吗?也许在 React 中?
【问题讨论】:
【参考方案1】:上面的答案并没有真正回答问题:
使用 OIDC 客户端库并不能解决这个问题,事实上据我所知,它甚至不使用刷新令牌。
将令牌存储在内存或会话存储中并不能解决问题,但会产生更多问题,见下文。
在某些情况下使用 AS 的会话 cookie 是不可行的。通常这是一个跨域 cookie,无法在其他站点上可靠地使用。这个概念称为“静默更新”,需要在 iframe 中使用跨域 cookie 来刷新令牌(使用 AS 会话)。这个概念听起来不错,但是随着浏览器和用户阻止越来越多的跨域跟踪机制,这使用起来确实很危险:在大多数情况下,无法检测到被阻止的 cookie(这会导致几秒钟后突然注销,尤其是在使用 OIDC 时)会话管理机制:刷新令牌时通过 AS 重定向也不是一个选项,因为在许多情况下,令牌是 JWT 并且仅在几分钟内有效,并且每隔几分钟就从应用程序重定向一次而破坏体验不是一个选项。
在浏览器中使用 PKCE 和授权代码流可以很好地使用和存储刷新令牌,但正如原始发布者所说,刷新时必须小心(尤其是刷新令牌只能使用一次时,这是需要的在浏览器环境中!)...
【讨论】:
【参考方案2】:如果您使用的是无 cookie SPA,最常见的解决方案是避免刷新令牌并执行以下操作:
使用OIDC client library 将令牌存储在内存或会话存储中(本地存储会增加很多浏览器问题) 使用授权服务器的会话 cookie(在浏览器选项卡之间共享)通过隐藏的 iframe 进行续订无烹饪水疗资源
如果我了解您的设置,以下是我的一些内容可能会有所帮助:
Client Side Open Id Connect Code React Sample React Sample Write Up【讨论】:
为什么这个答案有一个'-1'?【参考方案3】:为此,我使用页面可见性 API https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API。 当标签处于非活动状态时,我会取消续订订阅并在标签再次处于活动状态时设置续订。
我的 Angular 代码是:
constructor(
private router: Router,
private http: HttpClient,
private tokenService: TokenService,
@Inject(DOCUMENT) private readonly documentRef: Document,
)
this.getToken(); // From local Browser store
this.loggedIn = this.isAuthenticated();
this.status = new BehaviorSubject<boolean>(this.loggedIn);
this.documentRef.addEventListener("visibilitychange", () =>
console.log(document.hidden, document.visibilityState);
if (document.hidden)
this.cancelRenewal();
else
this.getToken();
this.loggedIn = this.isAuthenticated();
this.status.next(this.loggedIn);
this.scheduleRenewal();
, false);
【讨论】:
以上是关于OAuth 2.0 刷新令牌多个选项卡的主要内容,如果未能解决你的问题,请参考以下文章
在弹出窗口中打开 Google SignIn 用户身份验证,需要使用 OAuth 2.0 在同一选项卡本身中打开