I'm going to ask a conceptual question to see if there's any possible explanation for the behavior we are seeing in some rare situations. We have an angular 7.2 web application that use oidc-client-js for authentication. Hundreds of people use it every day with no issues. But we have come across three users who cannot login because it appears that the sessionStorage data is not written. We can see "No matching state found in storage" errors. And the behavior is machine-wide.
I just witnessed someone who was in this situation and I'm stumped. It was the same behavior and error across all of his browsers on that machine. It did not matter whether the browser was in private mode or not. The error is the same. If they use a different machine, everything works.
Can you explain why there are these rare cases where state is not written to sessionStorage across all browsers on a machine? Is there something that you are aware of that could cause this behavior?
Not sure. All browsers on that machine? Sounds like something on the OS preventing that? Is there even such a OS feature that affects all browsers?
In short, the "no state" issue is because the OIDC nonce (and some other info) can't be written to localStorage before redirecting to the STS (I've heard in incognito mode that prevents all storage for some browsers), or on return the matching state can't be found (maybe URL/origin misalignment so the storage is isolated from the domain they first went to compared to the one they returned to -- common when the user starts at app.com, but is redirected back to www.app.com for example).
I wish I knew if there were such a feature.
The URL/origin misalignment issue is interesting. I happen to have a detailed trace of the traffic and I wasn't seeing any misalignment.
The user ends up getting stuck in an infinite loop back and forth between Identity Server and the site. Here's a redacted sample of the infinite loop HTTP traffic:
(in this case, foo.com is the Identity Server and bar.com is the client site)
GET https://foo.com/sts/connect/authorize?client_id=myClient&redirect_uri=https%3A%2F%2Fbar.com%2Fauth-callback&response_type=id_token%20token&scope=openid%20profile%20email%20myApi&state=18d5376b849c4f3c8e29c6d66e88b89f&nonce=4f198a29d4af43cd8be2d32d7426d12e HTTP/1.1
Host: foo.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3
Referer: https://bar.com/auth-callback
Accept-Encoding: gzip, deflate, br
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
HTTP/1.1 302 Found
Location: https://bar.com/auth-callback#id_token=redacted&access_token=redacted&token_type=Bearer&expires_in=57600&scope=openid%20profile%20email%20myApi&state=18d5376b849c4f3c8e29c6d66e88b89f
Server: Microsoft-IIS/8.5
Request-Context: appId=cid-v1:9b5d8afc-77b3-4ba5-8987-1f8dc6fe6fee
X-Powered-By: ASP.NET
Date: Tue, 09 Apr 2019 22:07:34 GMT
Content-Length: 0
GET https://bar.com/auth-callback HTTP/2.0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
Referer: https://bar.com/auth-callback
Host: bar.com
HTTP/2.0 200
status: 304
last-modified: Fri, 22 Mar 2019 03:57:34 GMT
accept-ranges: bytes
server: Kestrel
request-context: appId=cid-v1:9b5d8afc-77b3-4ba5-8987-1f8dc6fe6fee
x-powered-by: ASP.NET
date: Tue, 09 Apr 2019 22:03:45 GMT
content-length: 3697
content-type: text/html
etag: "1d4e06361560571"
...and these are repeated infinitely.
In the catch on this ~/auth-callback page, I'd do some logging and see if something's not working properly. Also, why does the callback page trigger authorize, or is there another redirect back into your app (but presumably anonymous)?
We set the redirect_uri to be the /auth-callback page. That page ends up calling UserManager.signinRedirectCallback().
Here's the code:
completeAuthentication(): Promise<string> {
var self = this;
return new Promise(function (resolve, recject) {
self.manager.signinRedirectCallback().then(user => {
self.user = user;
if (user.state != null) {
resolve(user.state);
}
resolve("/");
}).catch(function (err) {
console.log(err);
resolve("/");
});
});
}
The callback page doesn't implement an AuthGuard in Angular so it shouldn't trigger authorize. The original request goes to the root of the site but the callback goes to /auth-callback with what appear to be fully valid tokens.
But this section:
}).catch(function (err) {
console.log(err);
resolve("/");
});
});
also returns to the root page, so that's why it's re-triggering login I suspect (the root is still not logged in, so triggers redirect to the STS).
so we need more info from the catch about why it's failing, and then perhaps show an error page instead?
Finally got the error:
Error: iat is in the future: 1556132890
at Function.e._validateJwt (main.cf459ef...js:1)
Ah, clock skew then on the client machine. That explains why all browsers fail :)
Yes - correcting the user's date/time on the machine fixes this issue. I'm closing this - thank you for the help in diagnosing.
How you solved this issue ? @akiander
This was fixed by correcting the time on the affected user's computer. It
was off by a few minutes and that caused this issue.
On Thu, Jun 20, 2019, 5:05 AM SampatPenugonda notifications@github.com
wrote:
How you solved this issue ? @akiander https://github.com/akiander
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/IdentityModel/oidc-client-js/issues/832?email_source=notifications&email_token=AANJKWFNNEFJK53BW3NHDWTP3NB55A5CNFSM4HH4WD32YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODYEZKAI#issuecomment-503944449,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AANJKWGJLUQDWUDEN53ARR3P3NB55ANCNFSM4HH4WD3Q
.

so , at first I login and then IS4 call my js client url"xx/callback.html?code=xxxx" , UserManager will call this function . But the stateStore is empty, there is no value at first. Why you get or set this stateStoreString here code ? At first should you set a value to stateStore ?

Here is my callback url , can you find out some errors?

As above image , if the stateStorage is emptyp , this description is so useless, why ?
I have this issue too. @blackcatpolice

at line 132 a default true has been passed which removes the state for me. I am not sure if this is causing an issue for this one. But could not find any doc around it to just try out.
Can some body help me in this. Am stuck from last 4 days at just this error.
Most helpful comment
This was fixed by correcting the time on the affected user's computer. It
was off by a few minutes and that caused this issue.
On Thu, Jun 20, 2019, 5:05 AM SampatPenugonda notifications@github.com
wrote: