title: Grant Provider OAuth state mismatch when accessing the two application modules simultaneously on same browser and user is not logged in yet
body: <p>I have been trying to implement Single SignOn(SSO). I have different frontend application modules which are running on different domain and they all utlize a single API server.</p>
  <ol>
  <li>SSO Server <a href="https://sso.app.com" rel="nofollow noreferrer">https://sso.app.com</a></li>
  <li>API Server <a href="https://api.app.com" rel="nofollow noreferrer">https://api.app.com</a></li>
  <li>Frontend Module 1 <a href="https://module-1.app.com" rel="nofollow noreferrer">https://module-1.app.com</a></li>
  <li>Frontend Module 2 <a href="https://module-2.app.com" rel="nofollow noreferrer">https://module-2.app.com</a></li>
  </ol>
  <h3>Authentication flow</h3>
  <p>The flow of authentication is FrontEnd Module check for token in the localstorage. If it do not find the token, it redirect the user to API server endpoint let say <a href="https://api.app.com/oauth/connect" rel="nofollow noreferrer">https://api.app.com/oauth/connect</a>.
  API server has the clientId and Secrets for the SSO server. API server set the url of Frontend module in the cookie(so that i can redirect the user back to initiator frontend module) and then redirect the request to SSO server where user is presented with login screen. User enters the creds there, SSO server validate the credientials, creates a session.
  Once credientials are validated, SSO server calls the API server Endpoint with user profile and access_token. API server gets the profile in the session and query and sign its own token and send that to frontend module through query params. On the frontEnd(React APP) there is a route just for this. In that frontend route I extract the token from queryParams and set in the localstorage. User is in the application.
  Similarly when user loads the FrontendModule-2 same flow happend but this time because Session is being created by SSO server when FrontendModule-1 flow ran. it never ask for login creds and sign the user in to the system.</p>
  <h3>Failing Scenario:</h3>
  <p>The scenario is, assume there is user JHON who is not logged in yet and do not have session. Jhon hit the &quot;Frontend Module 1&quot; URL in the browser. Frontend module check the localStorage for the token, it do not find it there, then Frontend module redirect the user to API server route.
  API server has the clientSecret and clientId which redirect the request to SSO server. There user will be presented with Login Screen.</p>
  <p>Jhon sees the login screen and left it as it is. Now Jhon opens another tab in the same browser and enter the URL of &quot;Frontend Module 2&quot;. Same flow happen as above and Jhon lands on login screen. Jhon left that screen as it is and moves back to the first tab where he has Frontend Module 1 session screen loaded up. He enter the creds and hit the login button. It give me error that session state has been changed.
  This error actually makes sense, because session is a shared.</p>
  <h3>Expectation</h3>
  <p>How do I achieve this without the error. I want to redirect the user to the same Frontend Module which initiated the request.</p>
  <p>Tools that I am Using</p>
  <ul>
  <li><a href="https://nodejs.org/" rel="nofollow noreferrer">NodeJS</a></li>
  <li><a href="https://www.npmjs.com/package/grant-express" rel="nofollow noreferrer">grant-express</a></li>
  <li><a href="https://www.npmjs.com/package/express-session" rel="nofollow noreferrer">express-session</a></li>
  </ul>
  <h3>Sample Implementation (API Server)</h3>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>require('dotenv').config();
  
  var express = require('express')
    , session = require('express-session')
    , morgan = require('morgan')
  var Grant = require('grant-express')
    , port = process.env.PORT || 3001
    , oauthConsumer= process.env.OAUTH_CONSUMER || `http://localhost`
    , oauthProvider = process.env.OAUTH_PROVIDER_URL || 'http://localhost'
    , grant = new Grant({
      defaults: {
        protocol: 'https',
        host: oauthConsumer,
        transport: 'session',
        state: true
      },
      myOAuth: {
        key: process.env.CLIENT_ID || 'test',
        secret: process.env.CLIENT_SECRET || 'secret',
        redirect_uri: `${oauthConsumer}/connect/myOAuth/callback`,
        authorize_url: `${oauthProvider}/oauth/authorize`,
        access_url: `${oauthProvider}/oauth/token`,
        oauth: 2,
        scope: ['openid', 'profile'],
        callback: '/done',
        scope_delimiter: ' ',
        dynamic: ['uiState'],
        custom_params: { deviceId: 'abcd', appId: 'com.pud' }
      }
    })
  
  var app = express()
  
  app.use(morgan('dev'))
  
  // REQUIRED: (any session store - see ./examples/express-session)
  app.use(session({secret: 'grant'}))
  // Setting the FrontEndModule URL in the Dynamic key of Grant.
  app.use((req, res, next) =&gt; {
    req.locals.grant = { 
      dynamic: {
        uiState: req.query.uiState
      }
    }
    next();
  })
  // mount grant
  app.use(grant)
  app.get('/done', (req, res) =&gt; {
    if (req.session.grant.response.error) {
      res.status(500).json(req.session.grant.response.error);
    } else {
      res.json(req.session.grant);
    }
  })
  
  app.listen(port, () =&gt; {
    console.log(`READY port ${port}`)
  })</code></pre>
  </div>
  </div>
  </p>