Failed silent Auth0 with error state does not match

I follow the sample in https://auth0.com/docs/quickstart/spa/vanillajs/05-token-renewal.
Here is my silent HTML written in ASP.NET CORE.

<!-- silent.html -->
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <script src="https://cdn.auth0.com/js/auth0/8.12.0/auth0.min.js"></script>
    <script>
        var webAuth = new auth0.WebAuth({
        domain: '@ViewBag.Domain',
        clientID: '@ViewBag.ClientID',
        scope: 'openid email user_metadata app_metadata',
        responseType: 'token id_token',
        redirectUri: 'http://localhost:5000'
    });
    </script>
    <script>
    debugger;
        webAuth.parseHash(window.location.hash, function (err, response) {
            debugger;
            console.log(response);
            parent.postMessage(err || response, 'http://localhost:5000');
    });
    </script>
</head>
<body>
</body>
</html>

My javascript application code

//Auth0.js version
<script src="https://cdn.auth0.com/js/auth0/8.12.0/auth0.min.js"></script>    

//Initialize Auth0.js
webAuth = new auth0.WebAuth({
            domain: AUTH0_DOMAIN,
            clientID: AUTH0_CLIENT_ID,
            redirectUri: 'http://localhost:5000',            
            responseType: 'code token id_token',
            scope: 'openid email user_metadata app_metadata',
            leeway: 60
        });

// Renew token
function renewToken() {
  webAuth.renewAuth(
    {
      redirectUri: 'http://localhost:54993/Auth0Management/silent',
      usePostMessage: true
    },
    function(err, result) {
      if (err) {    
        console.log(err);
      } else {     
        setSession(result);
      }
    }
  );
}

//Schedule Renewal
function scheduleRenewal() {
  var expiresAt = JSON.parse(localStorage.getItem('expires_at'));
  var delay = expiresAt - Date.now();
  if (delay > 0) {
     setTimeout(function() {
      renewToken();
    }, delay);
  }
}

But I got the following error
{error: “invalid_token”, errorDescription: “state does not match.”}
Please advices
@jmangelo Hope this will help you reproduce this issue

That error message is getting more common; I have not yet reproduced the situation, but if my memory is not failing me I don’t think last time I tried was as part of silent authentication so I’ll give it a go with that. Meanwhile, can you update the question with more information, for example, exact Auth0.js version, how Auth0.js is being initialized, how it’s being called for initial authentication, etc. In particular, mention anything that is different from the mentioned sample.

@it4 thanks for updating the question; I’m going to try to reproduce the issue now and we’ll keep you posted when I have more information.

I was able to reproduce the issue with that particular setup, but in that scenario this is mostly expected. When you don’t provide an explicit state Auth0.js generates one for you and stores it in web storage because in some flows HTTP redirects are required; this allows for Auth0.js to then validate the state when it receives the response.

In your setup you’re using two web origins:

  • http://localhost:5000 to serve the main application;
  • http://localhost:54993 to serve just the silent callback page.

Given that Auth0.js is starting the flow in origin one and completing (parsing the hash) in origin two then there is no state in web storage to match the one received and validation fails.

You can update your silent callback to just execute a postMessage of the hash itself which would mean that the hash would only get parsed in the original origin where the state is available in storage (web storage is per web origin). For example, update your silent.htmlto just:

  <script type="text/javascript">
    parent.postMessage(window.location.hash, "https://localhost:5000/");
  </script>

An even simpler approach would be to replace the usage of renewAuth with the checkSession method which does not require the additional silent.html as it makes use of web message response mode (it does the post message for you).

Thanks @jmangelo. I am using checkSession and all seem to work well