BrowserAuthError: interaction_in_progress: Interaction is currently in progress with azure/msal-browser@2.11.2
BrowserAuthError: interaction_in_progress: Interaction is currently in progress with azure/msal-browser@2.11.2
尝试使用@azure/msal-react@1.0.0-alpha.6 和@azure/msal-browser@2.11.2 在 React 应用程序中登录重定向时出现此错误。登录数据 returns 正确但控制台中出现异常。
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.
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
msalInstance.loginRedirect(loginRequest);
上面的代码片段接着做:
- 查看会话存储中的密钥 msal.[clientId].interaction.status 和重定向过程所需的其他临时值。如果这样的键存在并且它的值等于 'interaction_in_progress' 将抛出错误。
- 在会话存储 msal.[clientId] 中创建条目。interaction.status = interaction.status
- 将用户重定向到授权页面。
如果登录成功,用户将被重定向到包含您的代码的初始页面,并经过 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);
});
这可能不是一个干净的解决方案。但这至少在 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")
}
我发现在 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]
在开发过程中,您可能由于需要更正的编码问题而使登录流程处于进行中状态。您可以通过从浏览器中删除 msal.interaction.status cookie 来解决眼前的问题。当然,如果此问题仍然存在,则您需要使用此页面上建议的其他解决方案之一来解决问题。
我相信这是正确的答案和设置方法。这里的其他人让我找到了解决这个问题的线索。
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()
必须由您手动完成。请记住在您的应用程序中调用它的任何地方验证所有 async/await!并注意我是如何在我的主 authredirect.vue
文件中没有使用 handleRedirectPromise().then()
或任何东西的。仅 handleRedirectPromise()
加载。
Whosebug 上的其他解决方案建议诸如检查和删除会话中的交互状态之类的事情。不!如果您在登录后仍保留该状态,则表示该过程未正确完成! MSAL 自行清理!
完整详情:
了解 MSAL 在其整个生命周期中实际执行的操作非常重要(尤其是 redir 路径而不是弹出窗口),遗憾的是文档未能很好地完成工作。我发现这个小小的“旁注”非常非常重要:
"If you are calling loginRedirect
or acquireTokenRedirect
from a page
that is not your redirectUri
you will need to ensure
handleRedirectPromise
is called and awaited on both the redirectUri
page as well as the page that you initiated the redirect from. This is
because the redirectUri page will initiate a redirect back to the page
that originally invoked loginRedirect
and that page will process the
token response."
换句话说,您的重定向页面和 INVOKED 登录请求的页面都必须调用 handleRedirectPromise()
在页面加载时(或在 mounted() 上,在我的例子中,因为我使用的是 Vue)
就我而言,我有这个:
- http://localhost:8080/authredirect *
- http://localhost:8080/userprofile
*只有我的 AuthRedirect Uri 需要在我的 Azure AD 应用程序注册中注册为 RedirectUri。
所以这里是 loginRedirect() 生命周期,我不知道,并且浪费了一天的时间来整理:
- /UserProfile(或某些页面)调用登录请求
- 请求调用
handleRedirectPromise()
(它使用有关发出请求的位置的信息以及交互状态设置 MSAL,如果您不完成该过程,稍后会影响您)
- 然后调用
loginRedirect(loginRequest)
- -> 用户被重定向,完成登录
- Azure redir 回到 -> /AuthRedirect
- /AuthRedirect 调用
handleRedirectPromise()
,转发 -> /UserProfile
- /UserProfile 调用
handleRedirectPromise()
进行令牌的实际处理并在内部调用 setActiveAccount() 以将您的用户保存到会话。
该死。那很有趣。并且根本没有在文档中解释。
所以,您收到交互进行中错误的原因是因为您认为您已完成第 6 步。不! 第 7 步是 interaction_in_progress
状态得到解决和清理的地方,这样后续调用就不会出错!!
最终想法:
如果你有一个指定的登录页面,你希望用户总是 start/finish 来自(并且它本身就是注册的重定向 Uri),我想这些步骤会减少(没有像这里的第 6 步那样的转发).就我而言,我希望将用户重定向回他们可能因会话过期而被撞出的任何地方。所以我发现在每个页面加载时调用 handleRedirectPromise()
更容易,以防页面需要完成身份验证。或者,我可以将自己的重定向逻辑构建到一个专用的登录页面中,该页面可以让用户回到点击它之前的位置。只是对于 MSAL,我不知道该过程是在请求页面上完成的,而不是包含在我的 AuthRedirect 页面中,这让我很生气。
现在,如果我们能让 MS 提供更好的文档,说明 MSAL 的微妙和关键性质,并提供 Vue 插件(为什么只有 Angular 和 React 获得所有荣誉?: ) ), 那太好了!
您可以在打开 loginPopup 之前清除浏览器存储:
let msalInstance: PublicClientApplication = this._msauthService.instance as PublicClientApplication;
msalInstance["browserStorage"].clear();
更新@azure/msal-browser@2.21.0.
尝试使用@azure/msal-react@1.0.0-alpha.6 和@azure/msal-browser@2.11.2 在 React 应用程序中登录重定向时出现此错误。登录数据 returns 正确但控制台中出现异常。
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.
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
msalInstance.loginRedirect(loginRequest);
上面的代码片段接着做:
- 查看会话存储中的密钥 msal.[clientId].interaction.status 和重定向过程所需的其他临时值。如果这样的键存在并且它的值等于 'interaction_in_progress' 将抛出错误。
- 在会话存储 msal.[clientId] 中创建条目。interaction.status = interaction.status
- 将用户重定向到授权页面。
如果登录成功,用户将被重定向到包含您的代码的初始页面,并经过 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);
});
这可能不是一个干净的解决方案。但这至少在 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")
}
我发现在 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]
在开发过程中,您可能由于需要更正的编码问题而使登录流程处于进行中状态。您可以通过从浏览器中删除 msal.interaction.status cookie 来解决眼前的问题。当然,如果此问题仍然存在,则您需要使用此页面上建议的其他解决方案之一来解决问题。
我相信这是正确的答案和设置方法。这里的其他人让我找到了解决这个问题的线索。
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()
必须由您手动完成。请记住在您的应用程序中调用它的任何地方验证所有 async/await!并注意我是如何在我的主 authredirect.vue
文件中没有使用 handleRedirectPromise().then()
或任何东西的。仅 handleRedirectPromise()
加载。
Whosebug 上的其他解决方案建议诸如检查和删除会话中的交互状态之类的事情。不!如果您在登录后仍保留该状态,则表示该过程未正确完成! MSAL 自行清理!
完整详情:
了解 MSAL 在其整个生命周期中实际执行的操作非常重要(尤其是 redir 路径而不是弹出窗口),遗憾的是文档未能很好地完成工作。我发现这个小小的“旁注”非常非常重要:
"If you are calling
loginRedirect
oracquireTokenRedirect
from a page that is not yourredirectUri
you will need to ensurehandleRedirectPromise
is called and awaited on both the redirectUri page as well as the page that you initiated the redirect from. This is because the redirectUri page will initiate a redirect back to the page that originally invokedloginRedirect
and that page will process the token response."
换句话说,您的重定向页面和 INVOKED 登录请求的页面都必须调用 handleRedirectPromise()
在页面加载时(或在 mounted() 上,在我的例子中,因为我使用的是 Vue)
就我而言,我有这个:
- http://localhost:8080/authredirect *
- http://localhost:8080/userprofile
*只有我的 AuthRedirect Uri 需要在我的 Azure AD 应用程序注册中注册为 RedirectUri。
所以这里是 loginRedirect() 生命周期,我不知道,并且浪费了一天的时间来整理:
- /UserProfile(或某些页面)调用登录请求
- 请求调用
handleRedirectPromise()
(它使用有关发出请求的位置的信息以及交互状态设置 MSAL,如果您不完成该过程,稍后会影响您) - 然后调用
loginRedirect(loginRequest)
- -> 用户被重定向,完成登录
- Azure redir 回到 -> /AuthRedirect
- /AuthRedirect 调用
handleRedirectPromise()
,转发 -> /UserProfile - /UserProfile 调用
handleRedirectPromise()
进行令牌的实际处理并在内部调用 setActiveAccount() 以将您的用户保存到会话。
该死。那很有趣。并且根本没有在文档中解释。
所以,您收到交互进行中错误的原因是因为您认为您已完成第 6 步。不! 第 7 步是 interaction_in_progress
状态得到解决和清理的地方,这样后续调用就不会出错!!
最终想法:
如果你有一个指定的登录页面,你希望用户总是 start/finish 来自(并且它本身就是注册的重定向 Uri),我想这些步骤会减少(没有像这里的第 6 步那样的转发).就我而言,我希望将用户重定向回他们可能因会话过期而被撞出的任何地方。所以我发现在每个页面加载时调用 handleRedirectPromise()
更容易,以防页面需要完成身份验证。或者,我可以将自己的重定向逻辑构建到一个专用的登录页面中,该页面可以让用户回到点击它之前的位置。只是对于 MSAL,我不知道该过程是在请求页面上完成的,而不是包含在我的 AuthRedirect 页面中,这让我很生气。
现在,如果我们能让 MS 提供更好的文档,说明 MSAL 的微妙和关键性质,并提供 Vue 插件(为什么只有 Angular 和 React 获得所有荣誉?: ) ), 那太好了!
您可以在打开 loginPopup 之前清除浏览器存储:
let msalInstance: PublicClientApplication = this._msauthService.instance as PublicClientApplication;
msalInstance["browserStorage"].clear();
更新@azure/msal-browser@2.21.0.