title: React: AWS Cognito token endpoint returns 400 invalid_grant when being redirected by a Shopify store
body: <p>Our React app uses AWS Amplify and Cognito hosted UI for authentication. There is a feature in our app to link a Shopify store. To do that, we get the user's Shopify store URL and redirect the user to its admin panel to obtain permissions and access token. After the user grants permission, he is redirected again to our app.</p>
  <p>The problem occurs at this point. When looking at the console, we see something like this. <strong>Cognito token endpoint throws 400 invalid_grant error. This error goes away when we refresh the page, but we think there should be a better solution.</strong></p>
  <p>Can someone please provide us with advice on how to overcome these Cognito errors? All helpful advice is highly appreciated.</p>
  <p><a href="https://i.stack.imgur.com/vOoVp.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/vOoVp.png" alt="enter image description here" /></a></p>
  <p>The page that the user is redirected from the Shopify store is as follows.</p>
  <pre class="lang-js prettyprint-override"><code>import React, { useEffect } from &quot;react&quot;;
  import { Auth } from &quot;aws-amplify&quot;;
  import { useSelector, useDispatch } from &quot;react-redux&quot;;
  import * as api from &quot;../../services/api&quot;;
  
  const ShopifyAuthCallback = ({ history }) =&gt; {
    const classes = useStyles();
    const dispatch = useDispatch();
    const organizationId = useSelector(
      (state) =&gt; state.dashboard.userOrganizationId
    );
  
    useEffect(() =&gt; {
      Auth.currentSession()
        .then((res) =&gt; {
          const params = new URLSearchParams(window.location.search);
          const shopOrigin = params.get(&quot;shop&quot;);
          const authCode = params.get(&quot;code&quot;);
  
          api
            .post(`shopify/access-token`, {
              authCode: authCode,
              shopOrigin: shopOrigin,
              organizationId: organizationId,
            })
            .then((data) =&gt; {
              history.push(&quot;/&quot;);
            })
            .catch((error) =&gt; {
              console.error(error);
            });
        })
        .catch((error) =&gt; {
          console.log(error);
        });
    });
  
    return (
      &lt;div&gt;
        &lt;p&gt;Redirecting...&lt;/p&gt;
      &lt;/div&gt;
    );
  };
  
  export default ShopifyAuthCallback;
  </code></pre>
  <p>Amplify auth is set up in <code>App.js</code> as follows.</p>
  <pre class="lang-js prettyprint-override"><code>import React, { useEffect, useState } from &quot;react&quot;;
  import { createBrowserHistory } from &quot;history&quot;;
  import theme from &quot;./theme&quot;;
  import Routes from &quot;./Routes&quot;;
  import { withAuthenticator } from &quot;aws-amplify-react&quot;;
  import Amplify, { Auth } from &quot;aws-amplify&quot;;
  import aws_exports from &quot;./aws-exports&quot;;
  import { Router } from 'react-router-dom';
  import {useSelector } from &quot;react-redux&quot;;
  import { useDispatch } from &quot;react-redux&quot;;
  import * as api from &quot;services/api&quot;;
  
  Amplify.configure(aws_exports);
  Auth.configure();
  const browserHistory = createBrowserHistory();
  
  const App = () =&gt; {
    const dispatch = useDispatch();
  
    useEffect(() =&gt; {
      try {
        Auth.currentSession()
          .then(cognitoUser =&gt; {
            const { idToken: { payload } } = cognitoUser
            if (payload['custom:organization']) {
              // do something          }
            else {
              // do something else
            }
          })
          .then( async (res) =&gt; {
            // do something
          })
          .catch(err =&gt; {
            console.log(err);
          });
      } catch (e) {
        console.log(e);
      }
    }, []);
  
    return (
      &lt;ThemeProvider theme={theme}&gt;
        &lt;Router history={browserHistory}&gt;
          &lt;Routes /&gt;
        &lt;/Router&gt;
      &lt;/ThemeProvider&gt;
    );
  }
  
  const signUpConfig = {
    header: &quot;Create a new account&quot;,
    hideAllDefaults: true,
    defaultCountryCode: &quot;1&quot;,
    signUpFields: [
      {
        label: &quot;Name&quot;,
        key: &quot;name&quot;,
        required: true,
        displayOrder: 1,
        type: &quot;string&quot;
      },
      {
        label: &quot;Password&quot;,
        key: &quot;password&quot;,
        required: true,
        displayOrder: 2,
        type: &quot;password&quot;
      },
      {
        label: &quot;Email&quot;,
        key: &quot;username&quot;,
        required: true,
        displayOrder: 4,
        type: &quot;string&quot;
      }
    ]
  };
  
  export default withAuthenticator(App, {
    signUpConfig
  });
  </code></pre>
  <p><strong>EDIT:</strong></p>
  <p>These are the request and response details of the Cognito token endpoint.</p>
  <pre><code>General:
  
  Request URL: https://ogmo-dev.auth.eu-central-1.amazoncognito.com/oauth2/token
  Request Method: POST
  Status Code: 400 
  Remote Address: 35.156.210.187:443
  Referrer Policy: strict-origin-when-cross-origin
  
  Response:
  
  access-control-allow-credentials: true
  access-control-allow-origin: https://dev.ogmo.xyz/
  cache-control: no-cache, no-store, max-age=0, must-revalidate
  content-type: application/json;charset=UTF-8
  date: Sun, 25 Oct 2020 06:52:21 GMT
  expires: 0
  pragma: no-cache
  server: Server
  set-cookie: XSRF-TOKEN=&lt;token_value&gt;; Path=/; Secure; HttpOnly; SameSite=Lax
  status: 400
  strict-transport-security: max-age=31536000 ; includeSubDomains
  vary: Origin
  x-amz-cognito-request-id: b4cd564e-b0b1-42bf-a7a1-9361ce4db34d
  x-application-context: application:prod:8443
  x-content-type-options: nosniff
  x-frame-options: DENY
  x-xss-protection: 1; mode=block
  
  Request headers:
  
  :authority: ogmo-dev.auth.eu-central-1.amazoncognito.com
  :method: POST
  :path: /oauth2/token
  :scheme: https
  accept: */*
  accept-encoding: gzip, deflate, br
  accept-language: en-US,en;q=0.9
  content-length: 147
  content-type: application/x-www-form-urlencoded
  origin: https://dev.ogmo.xyz
  referer: https://dev.ogmo.xyz/
  sec-fetch-dest: empty
  sec-fetch-mode: cors
  sec-fetch-site: cross-site
  user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36
  
  Form data:
  
  grant_type: authorization_code
  code: 91a86bdadbe488ae1cd5ec10343a3461
  client_id: &lt;client_id&gt;
  redirect_uri: https://dev.ogmo.xyz/
  </code></pre>