【问题标题】:BrowserAuthError: interaction_in_progress: Interaction is currently in progress with azure/msal-browser@2.11.2BrowserAuthError:interaction_in_progress:当前正在进行与 azure/msal-browser@2.11.2 的交互
【发布时间】:2021-05-29 23:29:59
【问题描述】:

我在尝试使用 @azure/msal-react@1.0.0-alpha.6 和 @azure/msal-browser@2.11.2 在 React 应用程序中登录重定向时遇到此错误。登录数据正确返回,但在控制台中引发异常。

未捕获(承诺中)BrowserAuthError:interaction_in_progress: 目前互动正在进行中。请确保这 在调用交互 API 之前交互已经完成。

import * as msal from "@azure/msal-browser";

const msalConfig = {
  auth: {
      clientId: '995e81d0-',
      authority: 'https://login.microsoftonline.com/3a0cf09b-',
      redirectUri: 'http://localhost:3000/callback'
  },
  cache: {
    cacheLocation: "sessionStorage", // This configures where your cache will be stored
    storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
  }
};
const msalInstance = new msal.PublicClientApplication(msalConfig);
try {
  msalInstance.handleRedirectPromise()
    .then(res=>{
      console.log(res)
    })
    .catch(err => {
      console.error(err);
    });

  var loginRequest = {
    scopes: ["api://58ca819e-/access_as_user"] // optional Array<string>
  };
  msalInstance.loginRedirect(loginRequest);
} catch (err) {
  // handle error
  console.log(err)
}

例外

Uncaught (in promise) BrowserAuthError: interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API.
    at BrowserAuthError.AuthError [as constructor] (http://localhost:3000/static/js/vendors~main.chunk.js:852:20)
    at new BrowserAuthError (http://localhost:3000/static/js/vendors~main.chunk.js:8943:24)
    at Function.BrowserAuthError.createInteractionInProgressError (http://localhost:3000/static/js/vendors~main.chunk.js:9023:12)
    at PublicClientApplication.ClientApplication.preflightInteractiveRequest (http://localhost:3000/static/js/vendors~main.chunk.js:13430:30)
    at PublicClientApplication.<anonymous> (http://localhost:3000/static/js/vendors~main.chunk.js:12581:33)
    at step (http://localhost:3000/static/js/vendors~main.chunk.js:215:17)
    at Object.next (http://localhost:3000/static/js/vendors~main.chunk.js:146:14)
    at http://localhost:3000/static/js/vendors~main.chunk.js:118:67
    at new Promise (<anonymous>)
    at __awaiter (http://localhost:3000/static/js/vendors~main.chunk.js:97:10)
    at PublicClientApplication.ClientApplication.acquireTokenRedirect (http://localhost:3000/static/js/vendors~main.chunk.js:12565:12)
    at PublicClientApplication.<anonymous> (http://localhost:3000/static/js/vendors~main.chunk.js:13760:16)
    at step (http://localhost:3000/static/js/vendors~main.chunk.js:215:17)
    at Object.next (http://localhost:3000/static/js/vendors~main.chunk.js:146:14)
    at http://localhost:3000/static/js/vendors~main.chunk.js:118:67
    at new Promise (<anonymous>)
    at __awaiter (http://localhost:3000/static/js/vendors~main.chunk.js:97:10)
    at PublicClientApplication.loginRedirect (http://localhost:3000/static/js/vendors~main.chunk.js:13755:12)
    at Module.<anonymous> (http://localhost:3000/static/js/main.chunk.js:192:16)
    at Module../src/App.tsx (http://localhost:3000/static/js/main.chunk.js:292:30)
    at __webpack_require__ (http://localhost:3000/static/js/bundle.js:857:31)
    at fn (http://localhost:3000/static/js/bundle.js:151:20)
    at Module.<anonymous> (http://localhost:3000/static/js/main.chunk.js:2925:62)
    at Module../src/index.tsx (http://localhost:3000/static/js/main.chunk.js:3028:30)
    at __webpack_require__ (http://localhost:3000/static/js/bundle.js:857:31)
    at fn (http://localhost:3000/static/js/bundle.js:151:20)
    at Object.1 (http://localhost:3000/static/js/main.chunk.js:3570:18)
    at __webpack_require__ (http://localhost:3000/static/js/bundle.js:857:31)
    at checkDeferredModules (http://localhost:3000/static/js/bundle.js:46:23)
    at Array.webpackJsonpCallback [as push] (http://localhost:3000/static/js/bundle.js:33:19)
    at http://localhost:3000/static/js/main.chunk.js:1:67

【问题讨论】:

    标签: reactjs azure-active-directory msal


    【解决方案1】:
    msalInstance.loginRedirect(loginRequest);
    

    上面的代码接下来会做:

    1. 查看密钥 msal.[clientId].interaction.status 和重定向过程所需的其他临时值的会话存储。如果这样的键存在并且它的值等于 'interaction_in_progress' 将会抛出错误。
    2. 在会话存储 msal.[clientId].interaction.status = interaction.status 中创建条目
    3. 将用户重定向到授权页面。

    如果登录成功,用户将被重定向到带有您的代码的初始页面,并经过 1-3 步并捕获错误;

    下面的代码会删除会话存储中的所有临时值并完成身份验证重定向流程,但它是异步的,永远不会完成。

       msalInstance.handleRedirectPromise()
        .then(res=>{
          console.log(res)
        })
        .catch(err => {
          console.error(err);
        });
    

    解决办法是

    // Account selection logic is app dependent. Adjust as needed for different use cases.
    // Set active acccount on page load
    const accounts = msalInstance.getAllAccounts();
    if (accounts.length > 0) {
      msalInstance.setActiveAccount(accounts[0]);
    }
    
    msalInstance.addEventCallback((event) => {
      // set active account after redirect
      if (event.eventType === EventType.LOGIN_SUCCESS && event.payload.account) {
        const account = event.payload.account;
        msalInstance.setActiveAccount(account);
      }
    }, error=>{
      console.log('error', error);
    });
    
    console.log('get active account', msalInstance.getActiveAccount());
    
    // handle auth redired/do all initial setup for msal
    msalInstance.handleRedirectPromise().then(authResult=>{
      // Check if user signed in 
      const account = msalInstance.getActiveAccount();
      if(!account){
        // redirect anonymous user to login page 
        msalInstance.loginRedirect();
      }
    }).catch(err=>{
      // TODO: Handle errors
      console.log(err);
    });
    

    【讨论】:

    • 感谢您的提示。
    • 我在 MS 文档中没有看到任何类似的内容。为了让最基本的东西正常工作,必须来到 Stackoverflow 似乎很荒谬。感谢您发布此内容...但是您竟然奇迹般地想出了这个!
    • @dapug - 我在 GitHub 上阅读源代码,因为我遇到了同样的问题。
    【解决方案2】:

    这可能不是一个干净的解决方案。但这至少在 Vue.js 中确实有效。

    在您的 acquireToken() 逻辑旁边,添加此

    // Check Local or Session storage which may have already contain key 
    // that partially matches your Azure AD Client ID
    let haveKeys = Object.keys(localStorage).toString().includes('clientId')
    // That error will just go away when you refrest just once
    let justOnce = localStorage.getItem("justOnce");
    
    if (haveKeys && !justOnce) {
      localStorage.setItem("justOnce", "true");
      window.location.reload();
    } else {
      localStorage.removeItem("justOnce")
    }
    

    【讨论】:

      【解决方案3】:

      我发现在 msal.js v2 中,您可以检查 vanilla .js 代码中的交互状态,以查看是否存在正在进行的交互,如果您出于某种原因需要这样做:

      const publicClientApplication = new window.msal.PublicClientApplication(msalConfig);
      
      var clientString = "msal." + msalConfig.clientId + ".interaction.status";
      
      var interaction-status = publicClientApplication.browserStorage.temporaryCacheStorage.windowStorage[clientString]
      

      【讨论】:

        【解决方案4】:

        在开发过程中,您可能会因为需要更正的编码问题而使登录流程处于进度状态。您可以通过从浏览器中删除 msal.interaction.status cookie 来清除当前的问题。当然,如果此问题仍然存在,那么您需要使用此页面上建议的其他解决方案之一来解决此问题。

        【讨论】:

        • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
        • 这对我有用
        【解决方案5】:

        我相信这是正确的答案和设置方法。这里的其他人为我提供了解决此问题的线索。

        TLDR;像这样设置你的代码:

        // authRedir.ts  (or authRedir.vue inside mounted())
        await msalInstance.handleRedirectPromise();
        
        
        // mySignInPage.ts (or userprofile.vue, or whatever page invokes a sign-in)
        await msalInstance.handleRedirectPromise();
        
        async signIn(){
          const loginRequest: msal.RedirectRequest = {
            scopes: ["openid", "profile", "offline_access","your_other_scopes"]
            redirectUri: "http://localhost:8080/authredirect"
                };
        
          const accounts = msalInstance.getAllAccounts();
          if (accounts.length === 0) {
        
            await msalInstance.loginRedirect();
          }
        }
        

        如果您正确执行此操作,您将不需要共享代码@shevchenko-vladislav,其中setActiveAccount() 必须由您手动完成。请记住在应用程序中的任何位置验证所有异步/等待!并注意我是如何在我的主要authredirect.vue 文件中没有使用handleRedirectPromise().then() 或任何东西的。只需 handleRedirectPromise() 加载即可。

        Stackoverflow 上的其他解决方案提出了一些建议,例如检查和删除会话中的交互状态。不!如果您在登录后仍有该状态,则表示该过程未正确完成! MSAL 会自行清理!

        详细信息:

        了解 MSAL 在其整个生命周期中实际执行的操作非常重要(尤其是与弹出窗口相对的 redir 路径),遗憾的是文档未能做好。我发现这个小小的“旁注”非常非常重要:

        https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/errors.md#interaction_in_progress

        "如果您从页面调用loginRedirectacquireTokenRedirect 那不是您的redirectUri,您需要确保 handleRedirectPromise 在 redirectUri 上都被调用并等待 页面以及您从中发起重定向的页面。这是 因为redirectUri 页面会发起重定向回页面 最初调用loginRedirect 并且该页面将处理 令牌响应。”

        换句话说,您的重定向页面和INVOKED登录请求的页面都必须在页面加载时(或在mounted() 时调用handleRedirectPromise(),就我而言,因为我使用的是 Vue)

        就我而言,我有这个:

        • http://localhost:8080/authredirect *
        • http://localhost:8080/userprofile

        *只有我的 AuthRedirect Uri 需要在 Azure AD 中注册为 RedirectUri。

        所以这里是 loginRedirect() 生命周期,我不知道,花了一天时间整理:

        1. /UserProfile(或某些页面)调用登录请求
        2. 请求调用 handleRedirectPromise()(它会设置 MSAL,其中包含有关发出请求的位置和交互状态的信息,如果您不完成该过程,稍后会影响您)
        3. 然后调用loginRedirect(loginRequest)
        4. -> 用户被重定向,完成登录
        5. Azure 重定向返回 -> /AuthRedirect
        6. /AuthRedirect 调用handleRedirectPromise()转发到 -> /UserProfile
        7. /UserProfile 调用 handleRedirectPromise(),它实际处理令牌并在内部调用 setActiveAccount() 将您的用户保存到会话。

        当。那很有趣。并且根本没有在文档中解释。

        因此,您收到交互进行中错误的原因是您认为您已完成第 6 步。不! 第 7 步是解决和清理 interaction_in_progress 状态的地方,这样后续调用就不会被它绊倒!!

        最后的想法:

        如果您有一个指定的登录页面,您希望用户始终从其开始/结束(并且它本身就是注册的重定向 Uri),我想这些步骤将会减少(不像这里的第 6 步那样转发)。就我而言,我希望用户重定向回他们可能因会话到期而被淘汰的任何地方。因此,我发现在任何地方的每个页面加载时都更容易调用handleRedirectPromise(),以防万一该页面需要完成身份验证。或者,我可以将我自己的重定向逻辑构建到一个专用的登录页面中,该页面可以让用户回到他们点击它之前的位置。只是对于 MSAL,我不知道该过程是在请求页面上完成的,而不是包含在我的 AuthRedirect 页面中,这让我很不爽。

        现在,如果我们能让 MS 就 MSAL 的微妙和关键性质提供更好的文档,并提供 Vue 插件(为什么只有 Angular 和 React 获得所有荣耀?:)),那将是太好了!

        【讨论】:

          【解决方案6】:

          您可以在打开loginPopup之前清除浏览器存储:

          let msalInstance: PublicClientApplication = this._msauthService.instance as PublicClientApplication;
          msalInstance["browserStorage"].clear();
          

          【讨论】:

            猜你喜欢
            • 2021-12-19
            • 2022-11-07
            • 2022-01-13
            • 2018-08-20
            • 2022-09-30
            • 2021-09-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多