1

我正在为我的 Angular 应用程序使用 identityserver4 代码流。我正在使用angular-oauth2-oidc库。

我的配置是这样的:

   OauthConfig: AuthConfig = {
        issuer: 'http://mydomain.identityserver4',
        requireHttps: false,
        responseType: "code",
        redirectUri: window.location.origin + '/index.html',
        clientId: 'dev.code.flow',
        scope: 'openid profile offline_access my.api',
        logoutUrl: window.location.origin + '/index.html',
        postLogoutRedirectUri: window.location.origin + '/index.html'
    }

  private configureOauth(){
    this.oauthService.configure(OauthConfig);
    this.oauthService.tokenValidationHandler = new JwksValidationHandler();
    this.oauthService.loadDiscoveryDocumentAndLogin();
    this.oauthService.setupAutomaticSilentRefresh();
  }

登录应用程序后,库每 5 分钟发送一次刷新令牌请求。我可以在 chrome 开发人员工具中看到这一点。

但几个小时后,令牌刷新请求收到 400(错误请求)错误。错误信息是error: "invalid_grant"

这可能是什么原因?

4

1 回答 1

1

根据 OAuth2.0 协议,Refresh Token 和 Access Token 都有一定的生命周期。

看起来您的刷新令牌将在几个小时后过期。要解决此问题,您可以

  • 增加刷新令牌的生命周期(通常它们是长期存在的,应该安全处理)
  • 要求用户重新登录。
  • 可以使用滑动过期模式。

这来自 IdentityServer4 文档(链接):

AbsoluteRefreshTokenLifetime:刷新令牌的最大生命周期(以秒为单位)。默认为 2592000 秒/30 天。零允许刷新令牌,当与 RefreshTokenExpiration = Sliding 一起使用时,仅在经过 SlidingRefreshTokenLifetime 后才过期。

您可以在 IdentityServer4 的客户端配置中配置刷新令牌超时。

以下是我用来将用户重定向到登录页面的方法:

setupAutomaticLogoutInCaseOfTokenExpiry() {
    if (!this.oauthService.events) {
      return;
    }

    this.oauthService.events.subscribe((x: any) => {
      if (x.type === 'token_refresh_error') {
        // In case of internet connectivity
        if (x.reason && x.reason.error && x.reason.error.error === 'invalid_grant' &&
            x.reason.error.error_reason === 'refresh_token_not_found') {
          this.oauthService.logOut(true);
          (window as any).removeAllListeners();
          this.router.navigateByUrl(`/${Constants.PageUrls.Login}`);
        } else {
          // In case of no internet connectivity
          this.oauthService.stopAutomaticRefresh();
          const rereshTimeout = setTimeout(() => {
            this.oauthService.refreshToken().then(() => {
              this.oauthService.setupAutomaticSilentRefresh();
              clearTimeout(rereshTimeout);
            })
            .catch(() => {
              clearTimeout(rereshTimeout);
            });
          }, 5000);
        }
      }
    });
}
于 2020-08-31T07:17:55.660 回答