登录后,使用 angular-oauth2-oidc 时 hasValidAccessToken 始终为 true

Posted

技术标签:

【中文标题】登录后,使用 angular-oauth2-oidc 时 hasValidAccessToken 始终为 true【英文标题】:After login, hasValidAccessToken is always true when using angular-oauth2-oidc 【发布时间】:2021-11-02 13:39:00 【问题描述】:

我已经使用 Angular 12.2 实现了 angular-oauth-oidc(版本 12.1.0)。我使用 Keycloak 作为 SSO 登录没有问题,但我在库中遇到了奇怪的行为。

每次登录后,hasValidIdTokenhasValidAccessToken 方法都会返回 true,即使令牌已过期。该库似乎没有验证令牌过期时间。

我的配置文件如下:

export const authCodeFlowConfig: AuthConfig = 
    // Url of the Identity Provider
    issuer: 'http://localhost:8080/auth/realms/realmname',

    // URL of the SPA to redirect the user to after login
    redirectUri: window.location.origin + '/landing',

    // The SPA's id. The SPA is registerd with this id at the auth-server
    clientId: 'client-name',

    responseType: 'code',

    // set the scope for the permissions the client should request
    // The first four are defined by OIDC.
    // Important: Request offline_access to get a refresh token
    // The api scope is a usecase specific one
    scope: 'openid profile email',

    showDebugInformation: true,
  ;

我使用以下代码初始化库:

ngOnInit(): void 
    this.oauthService.configure(authCodeFlowConfig);
    this.oauthService.loadDiscoveryDocumentAndTryLogin().then(() => 
      if (this.oauthService.hasValidAccessToken()) 
        this.router.navigate(['home']);
      
      else 
        this.oauthService.initCodeFlow();
      
    );
  

最后,我检查令牌是否有效,并在警卫中使用以下条件:

canActivate(
    route: ActivatedRouteSnapshot, 
    state: RouterStateSnapshot) 
        var hasIdToken = this.oauthService.hasValidIdToken();
        var hasAccessToken = this.oauthService.hasValidAccessToken();
        var hasAccess = (hasIdToken && hasAccessToken)
            
        if (!hasAccess) 
            console.log('AuthGuard: Token not valid');
            this.router.navigate(['landing']);
        
        else 
            console.log('AuthGuard: Valid token');
        
            
        return hasAccess;

如果我以前登录,此方法总是返回true。如果没有事先登录,它会按预期返回false

如果我使用其他库进行令牌验证,我会在验证过期令牌时得到预期结果。

【问题讨论】:

【参考方案1】:

您发布的ngOnInit 将是异步的,可能需要-说- 150 毫秒才能完成。您的浏览器很可能会同步触发保护,因此之前初始化已经运行,因此将从访问令牌的存储中返回状态.

您需要:

Initialize in an async APP_INITIALIZER 确保在加载发现文档和所有爵士乐之前应用程序中没有任何内容运行;或 制作your guard asynchronous和make it wait for initialization on auth to be finished

您可以通过将自己的设置快速更改为延迟 2.5 秒来检查我的怀疑是否正确,以便我们可以合理地确定初始化已完全完成:

canActivate(
    route: ActivatedRouteSnapshot, 
    state: RouterStateSnapshot) 
        var hasIdToken = this.oauthService.hasValidIdToken();
        var hasAccessToken = this.oauthService.hasValidAccessToken();
        var hasAccess = (hasIdToken && hasAccessToken)
                   
        return new Promise((resolve) => 
          setTimeout(() => 
            if (!hasAccess) 
              console.log('AuthGuard: Token not valid');
              this.router.navigate(['landing']);
             else 
              console.log('AuthGuard: Valid token');
            
            resolve(hasAccess);
          , 2500);
        );

【讨论】:

以上是关于登录后,使用 angular-oauth2-oidc 时 hasValidAccessToken 始终为 true的主要内容,如果未能解决你的问题,请参考以下文章

POST 中的 Angular-oauth2-oidc loadDiscoveryDocument

angular-oauth2-oidc 中是不是有静默注销选项?

angular-oauth2-oidc 未设置 access_token

预期发现文档中的颁发者无效:带有 Azure B2C 的 angular-oauth2-oidc

Angular OpenID:在浏览器中加载应用程序之前重定向到登录

AngularJS + OAuth