microsoft-authentication-library-for-js: token renewal operation failed due to timeout MSAL
Hi,
Library : “@azure/msal-angular”: “^1.0.0-beta.5” “msal”: “^1.2.2”
I have integrated MSAL library with my angular 8 application. Everything works fine except i keep getting an error token renewal operation failed due to timeout as soon as the token is expired. I was wondering how to fix this.
Below is the MSAL_config that i am using :
"auth": {
"clientId": "xxxxx",
"authority": "https://login.microsoftonline.com/xxx",
"validateAuthority":"true",
"postLogoutRedirectUri": "http://localhost:4200/",
"navigateToLoginRequestUrl": true,
"redirectUri":"http://localhost:4200/"
},
"scopes":["user.read", "openid", "profile"],
"popUp": false,
"unprotectedResources": ["https://www.microsoft.com/en-us/"],
"protectedResourceMap":[["https://graph.microsoft.com/v1.0/me", ["user.read"]]],
"system":{
"loadFrameTimeout":10000
},
"cache": {
"cacheLocation": "localStorage",
"storeAuthStateInCookie":true
}
I have created a new token interceptor which pull the token everytime a http request is amde. Below is the code, here i face issue when the token is expired and i get the error. Please help me to resolve this as it is affecting the project.
if (this.authService.getAccount()) {
let token: string;
return from(
this.authService.acquireTokenSilent(this.loginRequest)
.then((response: AuthResponse) => {
token = response.idToken.rawIdToken;
const authHeader = `Bearer ${token}`;
if (!request.headers.has('Cache-Control')) {
request = request.clone({ headers: request.headers.set('Cache-Control', 'no-cache' + '') });
}
if (!request.headers.has('Pragma')) {
request = request.clone({ headers: request.headers.set('Pragma', 'no-cache' + '') });
}
if (!request.headers.has('Expires')) {
request = request.clone({ headers: request.headers.set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT' + '') });
}
return request.clone({
setHeaders: {
Authorization: authHeader,
}
});
})
)
.pipe(
mergeMap(nextReq => next.handle(nextReq)),
tap(
event => { },
err => {
if (err) {
var iframes = document.querySelectorAll('iframe');
for (var i = 0; i < iframes.length; i++) {
iframes[i].parentNode.removeChild(iframes[i]);
}
debugger
this.authService.handleRedirectCallback((err: AuthError, response) => {
debugger
this.authService.loginRedirect();
if (err) {
console.error('Redirect Error: ', err.errorMessage);
return;
}
debugger
this.authService.loginRedirect();
console.log('Redirect Success: ', response);
});
this.broadcastService.broadcast('msal:notAuthorized', err.message);
}
}
)
);
}
So in the above code it goes to the error but it never enters this.authService.handleRedirectCallback can someone please help me with this. I need the token to be renewed.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 9
- Comments: 89 (16 by maintainers)
I think I managed to get it working even for high POLLING_INTERVAL_MS values:
I’ve been able to resolve the token timeout issue by following the common issues guide found here: Common Issues
In our setup we had a redirect in the angular router from ‘/’ to ‘/some-url’ and we where redirecting msal to ‘/’, which would trigger a redirect by angular while acquiring the token. Msal did not like that. Now we have a redirect to (in our case) ‘/msal’ for msal, without angular redirecting under the hood and the problem seems to be resolved. Don’t forget to add the ‘/msal’ as an authenticated Redirect URI in the app registration in Azure Ad (B2C).
My question here is why does MSAL guard need to renew the token on each page request? even if the old token is not yet expired?
Yes, preventing navigation when you are in an iframe is a way to mitigate the behavior from the router that removes the hash. We show a similar workaround in the samples, but we’ll make sure this is better documented.
@jasonnutter I’m getting the same error. msal 1.3.1., msal-angular 1.0.0.
Auth only works right after I clear the browser cache. Hours later:
Here’s my code. There are 3 places where I’m configuring/calling MSAL. I don’t think I’m doing anything fancy. I’m basing it on the Angular 8 sample app.
app.module.ts
->NgModule
->imports
:app.module.ts
->NgModule
->providers
app.component.ts
->AppComponent
->ngOnInit
@jasonnutter @tnorling think this issue/library is going to be fixed before the end of the year? It’s absolutely bricking our spa. Our team is starting to catch a lot of heat for it since we put it in front of testers and they cant log in over 60% of the time. That, and issue #2492 have made testing our SPA impossible. It’s a nightmare.
@joshpitkin
loginRedirect
only requests an idToken, not an accessToken. The cache entry you are seeing that has scopes missing is actually the idToken. So when you callacquireTokenSilent
it’s looking for accessTokens which, by design, do not exist yet. We will be addressing this in #2206, which will updateacquireTokenSilent
to look for and return an idToken if that is what was requested.If your use case requires an accessToken you should call an interactive
acquireToken
method first, i.e.acquireTokenPopup
oracquireTokenRedirect
. If you are usingmsal@1.4.0
and you require only idTokens then this is a bug that will be addressed in the above PR. The workaround for now would be to downgrade to 1.3.4 in addition to calling the interactive methods first.Ok, I spent a day on this so I will share some findings and in case it helps anyone else…
In my implementation I don’t need/want any special consent scopes yet, just openid and profile which I believe are default.
However the loginRedirect() -> saveAccessToken() method doesn’t ever save those values in the “scope” property of the JSON object key for the tokens, because the value is undefined and it the key is JSON.stringified.
Then whenever a call to the acquireTokenSilent() method is called it doesn’t find any cached tokens! Tracked this down to getCachedToken() -> getAllAccessTokens() which has a condition looking for the “scopes” property to exist in the key from the storage items. Later it also looks for the value to match the requested scope.
The result is that every time I call acquireTokenSilent() it queues up another login redirect request in the hidden iframe, and eventually too many back-to-back repeat calls were causing intermittent “timeouts” from MSAL in my case.
So is this intentional / by design or do I have something setup wrong? Additional consent scopes are not required are they?
As a workaround I am duplicating that storage item and adding a “scopes” property to it with the values of “openid” and “profile”, but I have to re-create that every time the tokens are not loaded from cache.
☝️ same. I get the error once in awhile, not all the time. Not good UX.
@gunnamvasavi Don’t navigate when in an iframe:
Alternatively you can implement this https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-js-avoid-page-reloads
Apart from that, it may be necessary to disable initialNavigation: https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/1592#issuecomment-664818059