score:19
msalinstance.loginredirect(loginrequest);
the piece of code above does next:
- looks into session storage for key msal.[clientid].interaction.status and other temp values required for redirection process. if such key exist and its value equals 'interaction_in_progress' error will be thrown.
- creates entry in session storage msal.[clientid].interaction.status = interaction.status
- redirects user to auth-page.
in case of successful login user will be redirected to initial page with your code and go through 1-3 steps and will catch an error;
the piece of code below removes all temp values in session storage and completes auth redirection flow but it is async and never will be completed.
msalinstance.handleredirectpromise()
.then(res=>{
console.log(res)
})
.catch(err => {
console.error(err);
});
the solution will be
// 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);
});
score:-1
this may not be a clean solution. but this does work at least in vue.js.
next to your acquiretoken() logic, add this
// 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")
}
score:0
i have found that in msal.js v2 you can check interaction status in vanilla .js code to see if there is an interaction in progress, should you need to do this for some reason:
const publicclientapplication = new window.msal.publicclientapplication(msalconfig);
var clientstring = "msal." + msalconfig.clientid + ".interaction.status";
var interaction-status = publicclientapplication.browserstorage.temporarycachestorage.windowstorage[clientstring]
score:0
you can clear the browser storage before open the loginpopup:
let msalinstance: publicclientapplication = this._msauthservice.instance as publicclientapplication;
msalinstance["browserstorage"].clear();
score:0
update @azure/msal-browser@2.21.0.
score:3
during development, it is possible that you left the sign-in flow in a progress-state due to a coding issue that you will need to correct. you can clear the immediate problem by deleting the msal.interaction.status cookie from the browser. of course, if this problem persists, then you need to correct the problem using one of the other solutions suggested on this page.
score:5
i believe this is the correct answer and way to set this up. others here led me to clues to solve this.
tldr; set your code up like this:
// 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();
}
}
if you do this correctly, you wont need the code @shevchenko-vladislav shared, wherein setactiveaccount()
has to be manually done by you. remember to verify all async/await wherever you call this in your app! and notice how i did not use handleredirectpromise().then()
or anything, really, in my main authredirect.vue
file. just handleredirectpromise()
on load.
other solutions on stackoverflow suggest things like checking for and deleting the interaction state from the session. um, no! if you have that state left over after a sign-in, it means the process wasn't done right! msal cleans itself up!
full details:
it is super important to understand what msal is actually doing during it's entire lifecycle (especially the redir path as opposed to popup), and sadly the docs fail to do a good job. i found this little "side note" extremely, extremely important:
"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."
in other words, both your redirect page and the page that invoked the sign-in request must call handleredirectpromise()
on page load (or on mounted(), in my case, since i am using vue)
in my case, i have this:
- http://localhost:8080/authredirect *
- http://localhost:8080/userprofile
*only my authredirect uri needs to be registered as a redirecturi with my app registration in azure ad.
so here is the loginredirect() lifecycle, which i had no idea, and lost a days work sorting out:
- /userprofile (or some page) invokes a sign-in request
- the request calls
handleredirectpromise()
(which sets msal up with info about where the request was made and the interaction state that will bite you later if you dont complete the process) - and then calls
loginredirect(loginrequest)
- -> user is redirected, completes sign-in
- azure redir back to -> /authredirect
- /authredirect invokes
handleredirectpromise()
, which forwards along to -> /userprofile - /userprofile invokes
handleredirectpromise()
which does the actual processing of tokens and internally calls setactiveaccount() to save your user to session.
dang. that was fun. and not explained in the docs at all.
so, the reason you are getting the interaction-in-progress error is because you are thinking you're all done on step 6. nope! step 7 is where that interaction_in_progress
state gets settled and cleaned up so that subsequent calls wont trip up on it!!
final thought:
if you have a designated sign-in page you want users to always start/finish from (and itself is the registered redirect uri), i suppose these steps will be reduced (no forwarding like in step 6 here). in my case, i want the user redirected back to wherever they might have gotten bumped out of due to a session expiration. so i just found it easier to call handleredirectpromise()
on every single page load everywhere, in case said page it needs to finalize authentication. or, i could build my own redirect logic into a dedicated sign-in page that can put the user back where they were prior to hitting it. it's just that as for msal, i had no idea the process was finishing up on the requesting page rather than contained within my authredirect page, and that is what bit me.
now, if we could just get ms to provide far better docs on the delicate and critical nature of msal, and to provide a vue plugin (why does only angular and react get all the glory? :) ), that would be great!
Source: stackoverflow.com
Related Query
- BrowserAuthError: interaction_in_progress: Interaction is currently in progress with azure/msal-browser@2.11.2
- Support for the experimental syntax 'classProperties' isn't currently enabled
- Support for the experimental syntax 'jsx' isn't currently enabled
- You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file."
- Babel throwing Support for the experimental syntax 'jsx' isn't currently enabled
- support for the experimental 'jsx' isn't currently enabled
- In Laravel 5.7 React app, getting the error: 'classProperties' isn't currently enabled
- MUI Progress Indicator center align horizontally
- You are currently using minified code outside of NODE_ENV === 'production'. This means that you are running a slower development build of Redux
- How to show progress of Axios during get request (not download or upload)
- Progress bar with redux
- React progress element has a bug on IE10
- Storybook JS Interaction Testing with Enzyme - State Changes being Overidden
- React Router V4 - Warning: You tried to redirect to the same route you're currently on: "/home/dashboard"
- Redux-Form update field value from external interaction
- Why do modern JavaScript Frameworks discourage direct interaction with the DOM
- How to get loading progress in React.lazy and Suspense
- React.js: Avoid updates of currently edited input
- How can I create a progress bar for an API request in React Native?
- React + Firebase Storage + File upload and progress display
- Redux saga, axios and progress event
- React.js: how to make inline styles automatically update progress bar on state change
- show percentage number in reactjs material ui progress bar
- React jest and MSAL getting BrowserAuthError
- React Router: Show progress while loading
- React updating progress from a compute intensive function using setState
- Ignored attempt to cancel touchmove event with cancelable=false,for example because scrolling is in progress and cannot be interrupted
- Support for the experimental syntax 'decorators-legacy' isn't currently enabled
- How to get full test coverage with Jest and ReactJS, currently at 90.48% statements, 58.06% branch
- Fetching large amount of data with loop or recursion with progress percentage in React / React native
More Query from same tag
- How to update state for device width using Hooks in react
- Mongoose with mongodb how to return just saved object that have full or customize property with other collection?
- Unable to expose a component library in react with webpack and babel
- React Different Headers On Different Pages
- Jest styled-components 4.1.1 test are broken
- TypeError: Cannot read property 'message' of undefined
- How do I limit the max number of item rows in a DetailsList?
- How to use posts :title in url instead of :id in React.js
- React Hook SetState Causing Infinite Loop
- React: How can I use {props.children} in two layouts of the App structure
- Property 'type' does not exist on button
- Exposing Next.js Environment Variables to PWA's API-Platform
- Handle multiple input value change within an object
- Component didn't render when I setState in useEffect
- Jest doesn't follow files in a symlink folder and tries to use the main shared folder
- Get item details react/redux hooks
- Child component's input field not changing with change in parent's props react
- How can i change :hover styles on material-ui outlined select?
- ReactJS discarding all included css files
- React-Leaflet draw circle markers on map
- How do I install node.js version 14 in ubuntu 18. Version?
- Should I be binding also inbuilt React methods?
- Convert 5 minutes to 100% width on React Javascript
- How to parse Json arrays of objects in React JS
- Why does React conditional rendering render NaN?
- React + Typescript Higher Order Function "not assignable to type" error
- How can I prevent the unmount in React Components?
- Styling react-alice-carousel dots
- ComboBox doesn't show after setState or forceUpdate
- setState doesn t work in a promise. State undefined with React