Auto login and nonce/state error question

See original GitHub issue

I just upgraded to version 3.1 and i’m getting an error.

I’m not sure if this is applicable, but my site is configured to hit the domain, realize its insecure, then redirect to the login. (auto login)

In app.component.ts I’ve got this:

    let self = this;
    this.oauthService.configure(authConfig);
    this.oauthService.setStorage(localStorage);
    this.oauthService.tokenValidationHandler = new JwksValidationHandler();
    this.oauthService.loadDiscoveryDocumentAndLogin().then((res) => {
        self.oauthService.setupAutomaticSilentRefresh();
    });

So, my request hits the domain name, heads off to identity server and comes back with the id_token hash then throws this error:

validating access_token failed. wrong state/nonce. null yey1KhuQ9ewceuY7Qpbic4sWg5UAt8BJ6YYNryuY

When i debugged through this, I noticed that the nonce was saved, then on the second trip, the nonce wasnt in the local storage any more. So the comparison is between a valid nonce and null.

I tried creating login options with disableOAuth2StateCheck, but that just kicked the can down the road a bit. I got the error

Error validating tokens Wrong nonce: 3BAgeBU3kWkX5EiDKFDaGThnWj6pYqmsAXpf2HSO 

Here is the code I have now:

    this.oauthService.configure(authConfig);
    this.oauthService.setStorage(localStorage);
    this.oauthService.tokenValidationHandler = new JwksValidationHandler();
    let loginOptions = new LoginOptions();
    loginOptions.disableOAuth2StateCheck = true;
    this.oauthService.loadDiscoveryDocumentAndLogin(loginOptions).then((res) => {
        if (res)
            self.oauthService.setupAutomaticSilentRefresh();
    });

EDIT: I was able to work around this error by using the disable state check as shown above and commenting out the other state check in node_modules/angular-oauth2-oidc/angular-oauth2-oidc.umd.js. Lines 1702 - 1706.

What would the fix be?

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:26 (1 by maintainers)

github_iconTop GitHub Comments

10reactions
jeroenheijmanscommented, Aug 19, 2018

We were running into the same issue, and I think I’ve tracked down a repro. It’s quite reliable on my machine, but it does seem to be a timing issue or race condition, so the repro doesn’t always immediately work.

Repro

To reproduce:

  1. Run ng serve for this branch in my sample repo
  2. Open multiple (e.g. 4) Chrome windows with the demo app
  3. Open the devtools Console on all of them
  4. Keep the code open in VSCode
  5. Log in on one window
  6. Save any file to cause ng to reload all windows
  7. Click “Clear Storage” button
  8. Save any file to cause ng to reload all windows

Rinse and repeat step 7/8 until the issue arises, clearly visible in the dev tools console.

  • Result: 3 out of 4 windows encounter invalid_nonce_in_state, 1 of them runs just fine
  • Expected: all 4 windows to run just fine

Truth be told, this is a very artificial repro, but it is the most reliable one I could make. Various posters above also mention the issue, and I myself encountered a hard-to-repro version of this issue when users close Chrome, reopen it, and try to restore multiple tabs at once. I presume my artificial repro resembles the real problem well enough.

Debug info

To create useful debug info, I am logging all OAuthEvent events and also console.log(...)ing all StorageEvents where the key is 'nonce'.

Here’s a screenshot of a window that went bad, and the one that loaded just fine, side by side (other 2 windows that went bad not shown):

image

Here’s a rather large animated gif that shows this in full effect (when my mouse goes off-screen I go to VSCode to save a file and trigger ng’s hot-reloading):

repro-for-invalid-nonce-in-state-error

Hypothesis

I speculate that the issue arises because the nonce state check will validateNonceForAccessToken against the this._storage.getItem('nonce') which might’ve been changed in the mean time by another window/tab in the same browser.

I don’t think the browser or type of storage are the root cause of this issue. It is quite possible though that they affect the issue, as they might have different kinds of multi-threading, e.g. deciding to give larger chunks of CPU time to one tab at a time, hiding the actual issue.

Solution

Not really a clue. Perhaps the this._storage.getItem('nonce') call should be done earlier on and passed to the validateNonceForAccessToken(...) call instead?

Workarounds

In my sample repository, the master branch does have the errors, but that doesn’t seem to hurt too much, because:

But then again, it’s merely a sample repository, not really battle-tested. But perhaps it helps someone.

For what it’s worth, here’s a shortened version of my current login flow:

this.oauthService.loadDiscoveryDocument()
  .then(() => this.oauthService.tryLogin())
  .then(() => {
    if (this.oauthService.hasValidAccessToken()) { return Promise.resolve(); }
    return this.oauthService.silentRefresh()
      .then(() => Promise.resolve())
      .catch(result => {
        const errorResponsesRequiringUserInteraction = [
          'interaction_required',
          'login_required',
          'account_selection_required',
          'consent_required',
        ];

        if (result && result.reason && errorResponsesRequiringUserInteraction.indexOf(result.reason.error) >= 0) {
          console.warn('User interaction is needed to log in, we will wait for the user to manually log in.');
          // Could also call this.oauthService.initImplicitFlow() here...
          return Promise.resolve();
        }

        return Promise.reject(result);
      });
  })
  .then(() => this.isDoneLoadingSubject$.next(true))
  .catch(() => this.isDoneLoadingSubject$.next(true));
window.addEventListener('storage', (event) => {
  if (event.key === 'access_token' || event.key === null) {
    console.warn('Noticed changes to access_token (most likely from another tab), updating isAuthenticated');
    this.isAuthenticatedSubject$.next(this.oauthService.hasValidAccessToken());
  }
});

this.oauthService.events
  .subscribe(_ => {
    this.isAuthenticatedSubject$.next(this.oauthService.hasValidAccessToken());
  });

this.oauthService.events
  .pipe(filter(e => ['token_received'].includes(e.type)))
  .subscribe(e => this.oauthService.loadUserProfile());

this.oauthService.events
  .pipe(filter(e => ['session_terminated', 'session_error'].includes(e.type)))
  .subscribe(e => this.navigateToLoginPage());

this.oauthService.setupAutomaticSilentRefresh();
private isAuthenticatedSubject$ = new BehaviorSubject<boolean>(false);
public isAuthenticated$ = this.isAuthenticatedSubject$.asObservable();

private isDoneLoadingSubject$ = new ReplaySubject<boolean>();
public isDoneLoading$ = this.isDoneLoadingSubject$.asObservable();

public canActivateProtectedRoutes$: Observable<boolean> = combineLatest(
  this.isAuthenticated$,
  this.isDoneLoading$
).pipe(map(values => values.every(b => b)));
3reactions
vchaconcommented, Feb 8, 2018

Resolution of this issue, at least for us. It turns out that our server had the redirects deleted. When people used the HTTP address they were not redirected to the HTTPS address before starting the authentication process. The authentication process would start in HTTP and save the NONCE in the corresponding local/session storage. The redirect url parameter used was always HTTPS so upon authentication the user was redirected to the HTTPS address and would not find the NONCE in storage.

Once we corrected the server redirect to HTTPS://www.somesite.com/ our NONCE issue disappears as we found it in local storage.

Read more comments on GitHub >

github_iconTop Results From Across the Web

wrong user or password when using automatic logon! - TechNet
I'm having problem with automatic logon on a Windows 7 Professional, it's member of a domain. I have tried to set it up...
Read more >
Error when enabling auto login of macOS app using a helper
I had the exact same problem just now, and while looking for a solution found this (unanswered) question.
Read more >
Changed account to auto login, now su password does not work
I changed the user account to an auto login account, and now the user password is not accepted (i.e. authentication error) for installations,...
Read more >
Cannot do a Set Key operation when an auto-login wallet is ...
Advanced Networking Option - Version 12.1.0.1 to 12.2.0.1 [Release 12.1 to 12.2]: TDE Wallet Problem in 12c: Cannot do a Set Key operation...
Read more >
Auto login Windows Server 2012 - Super User
Try to use the registry key technique. You will need to have an account with a password for this to work. Run regedit.exe....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found