首页 > 解决方案 > 如何通过 Angular 中的隐式流进行静默刷新?

问题描述

所以我的问题是我们的令牌不会刷新。不仅如此,我们的整个网站都在重复。这是背景:

我们有以下身份验证配置(或多或少):

export const authConfig: AuthConfig = {
    issuer: '[censored]',
    redirectUri: window.location.origin + '/',
    silentRefreshRedirectUri: window.location.origin + '/assets/login-sources/silent-refresh.html',
    tokenEndpoint: '[censored]',
    loginUrl: '[same as tokenEndpoint]',
    clientId: '[censored]',
    scope: '[censored]',
    clearHashAfterLogin: true,
    oidc: true,
};

我们还有一个 loginService,它大致执行以下 onInit:

this.oauthService.configure(authConfig);
this.oauthService.tokenValidationHandler = new JwksValidationHandler();
// this.oauthService.setupAutomaticSilentRefresh(); - didn't work
this.oauthService.loadDiscoveryDocument([censored]).then((doc) => {
  // Subscribe to expiration event to refresh token.
  this.oauthService.events
    .pipe(filter(element => element.type === 'token_expires'))
    .subscribe(
      (a) => {
        console.log("Token is about to expire! Refreshing!");
        this.oauthService.silentRefresh().then(result => console.log(result)).catch(error => console.error(error));
      }
    );
  if (this.userid == null) {
    this.oauthService.tryLoginImplicitFlow().then((loggedIn) => {
      if (!loggedIn) {
        this.oauthService.initLoginFlow();
      }
    });
  }
});

问题:每当令牌过期时,都会发生以下事情:

所以我查看了silentRefresh() 的代码,它似乎适用于iframe。在所说的 iframe 中应该只是用于刷新令牌和“与主应用程序通信”的简单代码,请参见此处。我们甚至像这里一样实现了 refresh.html。然而,在我们的例子中,我们有一个 iframe,其中整个网站都是镜像的。这意味着我们有这样的东西:

html
  head /head
  body
    app-root /app-root
    iframe
      app-root /app-root
    /iframe
  /body
/html

因为对于每个silentRefresh(),iframe 都会被删除并重新添加到DOM 中,每次创建整个网站的新实例时。我做错了什么,我该如何解决这个问题?

版本:Angular 9 +“angular-oauth2-oidc”:“^9.0.1”,“angular-oauth2-oidc-jwks”:“^9.0.0”。

标签: javascriptangularoauth-2.0token

解决方案


处理这个问题的一种方法(我用于我的一些示例)是仅在主窗口上运行时呈现主应用程序。在我的小示例中,我将 index.html 用于主应用程序和更新 iframe,但会改变运行的代码。

我的是一个ReactJS 示例,这是我使用的技术。希望这有助于以不太侵入性的方式,尽管可能有替代解决方案。

if (window.top === window.self) {

    // Run the main ReactJS app
    render (
        <App />,
        document.getElementById('root'),
    );
} else {

    // Run a minimal app to handle the iframe renewal
    const app = new IFrameApp();
    app.execute();
}


推荐阅读