[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Other... Please describe:
Library version: 1.1.3
Ever since I upgraded from 0.2.4 to newer versions - currently the newest. I have nothing but problems which I never had before. I'm not sure if I'm doing something wrong. But I don't know what.
Currently and quite randomly this error occurs quite often. The only thing which helps then is to manually "logout" and log in again:
ClientAuthError: Invalid state. f7e035d3-ea01-4300-ba18-dc4ec5fd936c, state expected : null.
at ClientAuthError.AuthError [as constructor] (http://localhost:3000/static/js/1.chunk.js:59448:24)
at new ClientAuthError (http://localhost:3000/static/js/1.chunk.js:59579:24)
at Function.ClientAuthError.createInvalidStateError (http://localhost:3000/static/js/1.chunk.js:59624:12)
at UserAgentApplication.saveTokenFromHash (http://localhost:3000/static/js/1.chunk.js:58737:93)
at UserAgentApplication.processCallBack (http://localhost:3000/static/js/1.chunk.js:58093:23)
at UserAgentApplication.handleAuthenticationResponse (http://localhost:3000/static/js/1.chunk.js:58200:10)
at new UserAgentApplication (http://localhost:3000/static/js/1.chunk.js:57232:14)
at WebMsalService._this.createClient (http://localhost:3000/static/js/main.chunk.js:5126:21)
at new WebMsalService (http://localhost:3000/static/js/main.chunk.js:5144:11)
at _callee4$ (http://localhost:3000/static/js/main.chunk.js:2841:125)
at tryCatch (http://localhost:3000/static/js/1.chunk.js:168970:17)
at Generator.invoke [as _invoke] (http://localhost:3000/static/js/1.chunk.js:169189:22)
at Generator.prototype.<computed> [as next] (http://localhost:3000/static/js/1.chunk.js:169023:21)
at asyncGeneratorStep (http://localhost:3000/static/js/1.chunk.js:20628:24)
at _next (http://localhost:3000/static/js/1.chunk.js:20650:9)
at http://localhost:3000/static/js/1.chunk.js:20657:7
at new Promise (<anonymous>)
at http://localhost:3000/static/js/1.chunk.js:20646:12
at _getMsalClient (http://localhost:3000/static/js/main.chunk.js:2850:25)
at getMsalClient (http://localhost:3000/static/js/main.chunk.js:2830:25)
at _callee9$ (http://localhost:3000/static/js/main.chunk.js:3065:20)
at tryCatch (http://localhost:3000/static/js/1.chunk.js:168970:17)
at Generator.invoke [as _invoke] (http://localhost:3000/static/js/1.chunk.js:169189:22)
at Generator.prototype.<computed> [as next] (http://localhost:3000/static/js/1.chunk.js:169023:21)
at asyncGeneratorStep (http://localhost:3000/static/js/1.chunk.js:20628:24)
at _next (http://localhost:3000/static/js/1.chunk.js:20650:9)
at http://localhost:3000/static/js/1.chunk.js:20657:7
at new Promise (<anonymous>)
at http://localhost:3000/static/js/1.chunk.js:20646:12
at _getForClient (http://localhost:3000/static/js/main.chunk.js:3086:24)
at getForClient (http://localhost:3000/static/js/main.chunk.js:3041:24)
at _callee8$ (http://localhost:3000/static/js/main.chunk.js:3001:20)
at tryCatch (http://localhost:3000/static/js/1.chunk.js:168970:17)
at Generator.invoke [as _invoke] (http://localhost:3000/static/js/1.chunk.js:169189:22)
at Generator.prototype.<computed> [as next] (http://localhost:3000/static/js/1.chunk.js:169023:21)
at asyncGeneratorStep (http://localhost:3000/static/js/1.chunk.js:20628:24)
at _next (http://localhost:3000/static/js/1.chunk.js:20650:9)
Silent Token renewal should work.
Any pointers to what COULD be my problem are very welcome.
We're basically using MSAL like this.
My MSAL config:
const authConfig = {
auth: {
clientId: this.authConfiguration.clientId,
authority: policy || this.authConfiguration.signInPolicy, // https://login.microsoftonline.com/common"
validateAuthority: true,
redirectUri: `${this.appUrl}/login-complete`,
postLogoutRedirectUri: postLogoutRedirectUri || this.appUrl,
navigateToLoginRequestUrl: false
},
cache: {
cacheLocation: 'localStorage'
}
} as Configuration;
Log in:
client.loginRedirect({
scopes: this.getScopes(), // we provide some extra scopes here
extraQueryParameters: hints,
loginHint: hints.login_hint
});
Acquiring the token:
const response = await client.acquireTokenSilent({ scopes: [this.authConfiguration.clientId] });
I believe when you call acquireTokenSilent, you should pass the same scopes you used to login, correct @sameerag @pkanher617 ?
Hmm why should this be the case?
When loggin in I pass some extra scopes to consent. However then when acquiring the token I don't need this scopes. They scopes are need at another time in another place.
@Nasicus Your understanding is correct.
State expected being "null" made me curious, @pkanher617 by the time we check state in the saveTokenFromHash() we do not yet strip the GUID from my understanding. Why is the expected state showing as "null" then?
Sorry @sameerag for some reason I missed your message.
Anyway this is STILL happening from time to time.
In the mean time our login-object looks like this:
{
scopes: [this.authConfiguration.apiScope], // our custom api scope, something like this: api://<guid>/access_as_user
extraScopesToConsent: extraScopes, // [ "https://graph.microsoft.com/User.Read", "https://graph.microsoft.com/User.ReadBasic.All" ]
extraQueryParameters: hints, // includes: 'domain_hint' and 'login_hint'
loginHint: hints.login_hint
}
I guess you are right that we could / should remove the login_hint from the extra query parameters since we already pass it explicitly as the loginHint (on the old MSAL vesion this was not possible and we forgot to remove it). However we still need the domain_hint and I also strongly think (and hope ;) ) that this is not part of the problem.
@Nasicus domain_hint can still be passed as 'extraQueryParameters'. I find your usage okay, sticking to a single resource in scopes and adding a new resource scopes for 'extraScopesToConsent' would give you pre-consent while logging in for the 'tokens' you may request later.
We have recently fixed a bug #983 where we are clearing all cache that is not needed after a response is sent to the user and also tightened our acquireTokenSilent() code, #939. Both these PRs should remove any unneeded state lurking around ( potentially causing the above issue).
The release plan is to get a beta build out sometime next week. Can you test it before the official release?
One more observation:
authority: policy || this.authConfiguration.signInPolicy
If you are using B2C authority, we recommend setting validateAuthority: false as they can be customized and the validation happens at the end point. For AAD you can keep it on.
The problem is, that it happens very seldom and I don't know when exactly. So even if I would test it, I could not say with guarantee that it works.
How would I need to update: Simply via NPM or otherwise? I can do it locally and see if it occurs again...
Two questions @sameerag :
new UserAgentApplication (e.g. initially we create one without a config, just to catch the callback, same for acquiring the token, but for example for a login call we create the client with a different config (with the scopes to consent). Could this be a problem? Timing issues? Overriding each other?storeAuthStateInCookie: true ? because this is described here: https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/734 (I think I remember that we already tried this at some point and it didn't help, but I'm not entirely sure anymore)I'm confused as to how the storeAuthStateInCookie: true change could fix the #734 issue on Edge browsers... according to the documentation, I was under the impression that storeAuthStateInCookie was only needed for IE.
@Nasicus I am interested to know more about the use cases where you need to create new instances of msal js. Are these for the same application (clientId) ? Why would you need a new msal js instance for scopes, when you can add scopes in a request?
@AndrewCraswell I agree with you, storeAuthStateInCookie: true is recommended to be set for use cases where the browser storage is cleared on redirect, which is the case with IE trusted zones.
The upcoming release should have fixes to address any left over state from requests left unresolved.
@sameerag
Ok the with different scope may habe been confusing. But I'll try to explain the use case.
So our app works basically with 3 different MSAL-login types:
https://login.microsoftonline.com/commonhttps://login.microsoftonline.com/<specific-tenant-ids>Which configuration to use (i.e. how to create the UserAgentApplication) we only know when a user clicks the corresponding button on our login screen, but at the same time we also create an instance in the constructor of our "wrapper"-class (see below) so token-callbacks and stuff like this can be handled immediately.
We created our app like that, that the UserAgentApplicaiton is wrapped in our own class, and basically for each method call (the constructor, login, acquireTokenAsync, isAuthenticated, etc...) we create a new instance of the UserAgentApplication. We always thought this is okay and we also did the same thing on the older MSAL version (0.2.4) where we never had any issues at all.
Sometimes creating the client differently (even for the same "login-type") this may even be required. For example when we call logout we sometimes have different postLogoutUrls which are determined only at runtime and basically can only be passed when logout is actually clicked and since the logout method does not have an overload which accepts this parameter, we have to create a new instance for this too, where we can pass in the correct configuration.
That's why I asked if multi instance is a problem, because if it is, we might need to find a solution in our project to prevent that.
EDIT:
I just rewrote our wrapper so that the instance is cached (as a singleton global object) as long as the config doesn't change and / or no specific config is passed to the creation method. This would mean that once a user is logged in we almost never create more than one instance anymore.... will see if this reduces the invalid state bugs.
@jasonnutter any updates on this issue? We are facing this as well with MSAL.js (1.1.3). But in our case, it only happens for new users that are invited into our AAD, the very first time they sign-in.
The result is that the user has to click the login button twice, the first time it fails with ClientAuthError: Invalid state. *******, state expected : null.
ClientAuthError: Invalid state. *******, state expected : null.
at t [as constructor]
at new t
at Function.t.createInvalidStateError
at e.saveTokenFromHash
at e.processCallBack
at e.handleRedirectCallback
at new e
at
at kp
at Dp
e.authCallback
e.authErrorHandler
e.processCallBack
e.handleRedirectCallback
Users can register themselves as members in our system. When a user registers we invite them into our own AAD tenant as members. The user gets an e-mail and fills out the account details in AAD which then asks for consent for our application. When this is done the user gets redirected to the login screen of our Angular front-end. When the user now clicks the login button we redirect them AAD using the loginRedirect function of MSAL.js. Since the user is already logged in AAD as a result of the invite flow he is instantly redirected back to our Angular front-end however at this point we get the following error: ClientAuthError: Invalid state. ***** state expected : null.”
@sanderaernouts Can you try 1.2.0-beta.3 and let us know if you are still seeing that issue?
@jasonnutter I tried it just now on our DEV environment. Looks like the issue is gone with 1.2.0-beta.3. What is the ETA on 1.2.0?
Hopefully by next monday. There is a beta.4 in pipeline and we plan to release 1.2.0 after that.
UPDATE: We are currently working on beta.5, and we will have a code freeze until Dec 4th coming up. Once this code freeze is lifted, we will release 1.2.0. Thanks for your patience.
i had updated to the current version and token renew works fine and token renewed on server but with following error in console.
(index):1 Unsafe JavaScript attempt to initiate navigation for frame with URL 'https://myapp.example.com/#/dashboard/example' from frame with URL 'https://myapp.example.com/#id_token=ey...&client_info=...&state=04...&session_state=75...'.
The frame attempting navigation of the top-level window is sandboxed, but the flag of 'allow-top-navigation' or 'allow-top-navigation-by-user-activation' is not set.
(anonymous) @ (index):1
(index):1 Uncaught DOMException: Failed to set the 'href' property on 'Location': The current window does not have permission to navigate the target frame to 'https://myapp.example.com/#id_token=eyJ....&client_info=ey....&state=04....&session_state=75...'.
at https://myapp.example.com/:1:1124
(anonymous) @ (index):1
App.js:58 2.25.1
On Local is failed and shows error
Error State Mismatch.Expected State: null,Actual State: 4sdfsa7d9-d125-428d-4350-542e153263aa8
@AbhaysinghBhosale If you the "Unsafe JavaScript attempt to initiate navigation..." error again, try opening the second url in its own tab (see what happens), as its likely that the request was not properly formatted or had some other kind of critical error.
Hello
I have been having similar issues when migrating from react-aad-msal to direct msal (for more fine grained control).
react-aad-msal did not have this issue but when I migrated to msal with identical configuration parameters and loginRedirect calls msal failed while react-aad-msal worked.
After digging into it a bit more I found that it was caused by when I invoked msal.handleRedirectCallback. If the call happens too late I get the above error.
I was able to break my working version by delaying the register:
setTimeout(function() {
instance.handleRedirectCallback(...)
}, 500);
I am using msal with React and the delayed useEffects were the cause of my issues
Ciaran
@cliedeman Ah interesting, thanks for the sharing, good to know. We'll probably want to add fix in the library to mitigate that.
@cliedeman Can you please open a new issue (specifically on the issue of delaying handleRedirectCallback) so that we can track? Thanks!
@anandyadavMSFT
I can confirm the same behavior in Angular 8, error is the same as in the first post
it can be workarounded using setTimeout (like @cliedeman did) but it can create race conditions
Most helpful comment
Hello
I have been having similar issues when migrating from react-aad-msal to direct msal (for more fine grained control).
react-aad-msal did not have this issue but when I migrated to msal with identical configuration parameters and loginRedirect calls msal failed while react-aad-msal worked.
After digging into it a bit more I found that it was caused by when I invoked msal.handleRedirectCallback. If the call happens too late I get the above error.
I was able to break my working version by delaying the register:
I am using msal with React and the delayed useEffects were the cause of my issues
Ciaran