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 在同一选项卡本身中打开

Blazor Server 如何跨多个选项卡和刷新保存数据

打开新的浏览器选项卡会使 Django 的 CSRF 令牌无效,从而阻止表单提交

页面刷新和多个选项卡上的 Vuex 状态

从选项卡注销,不适用于所有其他选项卡

如何在浏览器多个选项卡中处理用户注销?