OidcClient.readSigninResponseState:在存储中找不到匹配的状态 - oidc-client-js (Angular)

Posted

技术标签:

【中文标题】OidcClient.readSigninResponseState:在存储中找不到匹配的状态 - oidc-client-js (Angular)【英文标题】:OidcClient.readSigninResponseState: No matching state found in storage - oidc-client-js (Angular) 【发布时间】:2020-08-23 04:02:32 【问题描述】:

我正在使用oidc-client library 在我的 Angular(9) 应用程序中与 Azure AD 集成。 signinRedirect() & signinSilent() 函数按预期工作。但是对于signinPopup()它在浏览器 url 片段中成功获取了访问令牌,但它抛出了下面提到的错误

app.component.ts:83 错误:在存储中找不到匹配的状态 在 oidc-client.min.js:1

令人惊讶的是,在 signin-callback.html 中,当我将 response_type 作为查询 var userManager = new Oidc.UserManager(response_mode: "query"); 传递时,登录弹出窗口成功但登录重定向失败并抱怨

错误:无响应状态

我最初关注了这个article。

这是我的服务代码:

import  Injectable  from '@angular/core';
import  UserManager, UserManagerSettings, User  from 'oidc-client';

import  environment  from 'src/environments/environment';

@Injectable(
  providedIn: 'root'
)
export class AuthService 
  private userManager: UserManager;

  constructor() 
    this.instantiate();
  

  private instantiate() 
   this.userManager = new UserManager(this.getOidcSettings());
  

  public async signinRedirect(): Promise<any> 
    return this.userManager.signinRedirect();
  

  public async signinSilent(): Promise<User> 
    return this.userManager.signinSilent();
  

  public async signinPopup(): Promise<User> 
    return this.userManager.signinPopup();
  

  public async signoutRedirect(): Promise<any> 
    this.userManager.signoutRedirect();
    this.userManager.clearStaleState();
  

OIDC 设置:

const userManagerSettings: UserManagerSettings = 
      client_id: 'my clientid',
      authority: 'my authority',

      redirect_uri: 'http://localhost:4200/assets/oidc/signin-callback.html',
      silent_redirect_uri: 'http://localhost:4200/assets/oidc/silent-refresh-callback.html',
      post_logout_redirect_uri: 'https://localhost:4200/',

      response_type: 'token',
      response_mode: 'fragment',
      scope: 'my api scope',

      loadUserInfo:false
    ;

signin-callback.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/oidc-client/1.10.1/oidc-client.min.js"></script>
    <script>
      var userManager = new Oidc.UserManager();

      userManager.signinRedirectCallback().then(
        (user) => 
          alert('signin redirect successful.');
          window.history.replaceState(
            ,
            window.document.title,
            window.location.origin
          );
          window.location = '/';
        ,
        (err) => 
          alert('Error caught in signinRedirectCallback()');
          console.log('Error caught in signinRedirectCallback().');
          console.error(err);
        
      );

      userManager.signinPopupCallback().then(
        (user) => 
          alert('signin pop up successful.');
          window.history.replaceState(
            ,
            window.document.title,
            window.location.origin
          );
          window.location = '/';
        ,
        (err) => 
          alert('Error caught in signinPopupCallback()');
          console.log('Error caught in signinPopupCallback().');
          console.error(err);
        
      );
    </script>
  </head>
  <body></body>
</html>

silent-refresh-callback.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/oidc-client/1.10.1/oidc-client.min.js"></script>
    <script>
      var userManager = new Oidc.UserManager();
      userManager.signinSilentCallback().catch((err) => 
        console.log('Error caught in signinSilentCallback().');
        console.error(err);
      );
    </script>
  </head>
  <body></body>
</html>

【问题讨论】:

清除我的浏览器缓存(从设置)为我解决了这个问题。在某些情况下,我必须手动进入“应用程序”选项卡,然后在您进入站点主页后,清除会话和状态存储。这解决了我的问题。 你找到解决方案了吗? 【参考方案1】:

我们遇到过类似的问题,部分用户间歇性地出现此错误。到目前为止,我们已经了解到造成这种情况的两个具体原因:

    部分用户的系统时钟设置与当前实际时间相差超过 5 分钟(在 oidc-client-js 中 clockSkew 默认为 5 分钟)

    一些用户正在共享和重复使用由 Identity Server 生成的带有安全参数的唯一生成的登录 URL。可以使用身份服务器登录,但是像 nonce 这样的安全变量不匹配(并最终在 oidc-signin 回调中抛出“No matching state found in storage”错误)

【讨论】:

你是如何解决第二个问题的?对于如何防止这种情况发生,您有什么建议吗? @MarianoSoto 不幸的是,我们没有解决 #2,因为它已被取消优先级。一旦我们深入研究它,我们可能会寻找一些方法来加强对身份服务器的要求,以便它可以拒绝例如重复使用的登录链接。 (例如找出一种方法来拒绝 url 中过时的安全参数并强制重定向以重新启动登录流程)【参考方案2】:

这也发生在我身上,就我而言,我们使用 https 配置了 Identity Server 站点,我正在尝试访问旧的书签 URL,它被存储为 http。

这导致了同样的 OIDC 问题。将 URL 恢复为 https 后,一切都对我有用。

【讨论】:

以上是关于OidcClient.readSigninResponseState:在存储中找不到匹配的状态 - oidc-client-js (Angular)的主要内容,如果未能解决你的问题,请参考以下文章