amplify-js: 'redirect_mismatch' error with hosted UI

Note: If your question is regarding the AWS Amplify Console service, please log it in the official AWS Amplify Console forum

** Which Category is your question related to? ** Auth / Hosted UI

** What AWS Services are you utilizing? ** Cognito, Amplify Console

** Provide additional details e.g. code snippets ** Hi,

My auth work flow worked fine with the hosted UI when I was only using http://localhost:3000/ as the sign in/sign out url. When amplify console created a dev build, it hosted the frontend on a different url (https://dev.<some_id>.amplifyapp.com/ in my case). When opening the hosted UI from this url, it complained “redirect_mismatch”, which is understandable since I only have localhost configured in cognito at this point.

I ran amplify update auth to add the console provided app url to the sign in/sign out urls, amplify push then git commit & git push to make the amplify console pick up the changes. However, the console hosted app still gave me “redirect_mismatch” error. I checked the aws-export.js file and cognito console, the redirect urls are exactly the same (“http://localhost:3000/,https://dev.<some_id>.amplifyapp.com/”). I used Chrome’s inspection tool to check the actual redirect_uri string in the HTTP request, also exactly the same. I have no idea why the hosted UI is complaining mismatch.

Then I found out the app stopped working on my localhost, too. Same “redirect_mismatch” error. 😦

image

Any help will be appreciated!

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 33 (9 by maintainers)

Most upvoted comments

Sorry guys but in fact, this is a normal behavior.

Setup amplify add auth with two URLs: “http://localhost:3000/,https://master.xxx.amplifyapp.com/” to add the sign in/sign out URLs, amplify push then git commit & git push to make the amplify console pick up the changes.

Then you get a redirect_mismatch error locally and online https://master.xxx.amplifyapp.com/

Why ? There is no way for the react app. to know by default which URLs to use when you have two or more URLs. You must inform the app. to use one of these URLs. You can do it like that:

What can you do ? After looking in the doc., you find pretty much a solution here: https://aws-amplify.github.io/docs/js/authentication#react-components

import Amplify, { Auth } from 'aws-amplify'
import config from './aws-exports'

and,

// copied from serviceWorker.js to know if it is localhost or not
const isLocalhost = Boolean(
  window.location.hostname === 'localhost' ||
    // [::1] is the IPv6 localhost address.
    window.location.hostname === '[::1]' ||
    // 127.0.0.1/8 is considered localhost for IPv4.
    window.location.hostname.match(
      /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
    )
);

// by default, say it's localhost
const oauth = {
  domain: 'xxx.auth.us-east-2.amazoncognito.com',
  scope: ['phone', 'email', 'profile', 'openid', 'aws.cognito.signin.user.admin'],
  redirectSignIn: 'http://localhost:3000/',
  redirectSignOut: 'http://localhost:3000/',
  responseType: 'code' // or 'token', note that REFRESH token will only be generated when the responseType is code
};

// if not, update the URLs
if (!isLocalhost) {
  oauth.redirectSignIn = 'https://master.xxx.amplifyapp.com/';
  oauth.redirectSignOut = 'https://master.xxx.amplifyapp.com/';
}

// copy the constant config (aws-exports.js) because config is read only.
var configUpdate = config;
// update the configUpdate constant with the good URLs
configUpdate.oauth = oauth;
// Configure Amplify with configUpdate
Amplify.configure(configUpdate);

Full code & example You can find a demo here that also work in localhost: https://master.d3h5j4begww46c.amplifyapp.com/ And a github fork (from dabit3): https://github.com/arelaxtest/amplify-auth-demo

Personnally, I do something like

var urlsIn = config.oauth.redirectSignIn.split(",");
var urlsOut = config.oauth.redirectSignOut.split(",");
const oauth = {
  domain: config.oauth.domain,
  scope: config.oauth.scope,
  redirectSignIn: config.oauth.redirectSignIn,
  redirectSignOut: config.oauth.redirectSignOut,
  responseType: config.oauth.responseType
};
var hasLocalhost  = (hostname) => Boolean(hostname.match(/localhost/) || hostname.match(/127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}/));
var hasHostname   = (hostname) => Boolean(hostname.includes(window.location.hostname));
var isLocalhost   = hasLocalhost(window.location.hostname);
if (isLocalhost) {
  urlsIn.forEach((e) =>   { if (hasLocalhost(e)) { oauth.redirectSignIn = e; }});
  urlsOut.forEach((e) =>  { if (hasLocalhost(e)) { oauth.redirectSignOut = e; }});
}
else {
  urlsIn.forEach((e) =>   { if (hasHostname(e)) { oauth.redirectSignIn = e; }});
  urlsOut.forEach((e) =>  { if (hasHostname(e)) { oauth.redirectSignOut = e; }});
}
var configUpdate = config;
configUpdate.oauth = oauth;
Amplify.configure(configUpdate);

Same issue. I get redirect_mismatch when using more than one redirect url

@jordanranz 's fix totally worked for me!

The correct solution is either that the SDK should handle this or the documentation should make a disclaimer about this snippet of code.

@YangMann do you’ve a repro project you could share with us?

For folks on this thread – I recently experienced this issue myself and used the fix listed above. It works but I agree that our docs need to be updated and this should be fixed in the way the Amplify config state is created. This is now marked as a bug and will be addressed soon. https://github.com/aws-amplify/amplify-js/issues/5565.

Hi Guys, any plans on fixing this issue?

@attilah I have a question: how is the redirect uri populated when calling Auth.federatedSignIn()?

redirect uri populated from oauth.redirectSignIn at aws-export.js or Auth.configure({ oauth: {redirectSignIn: “…”} }).

i got the problem when using two redirect uris, change it to one uri fix my problem.

@attilah I have a question: how is the redirect uri populated when calling Auth.federatedSignIn()?

I wish the documentation updates soon. I was facing this issue too, and in my case, I had more than 2 domains. I followed this comment and tidy that up a bit to suit my needs. I hope the following solution can help someone:

import awsconfig from '../aws-exports'
import {Amplify} from 'aws-amplify'

const configureAmplify = () => {
  const urlsIn = awsconfig.oauth.redirectSignIn.split(',')
  const urlsOut = awsconfig.oauth.redirectSignOut.split(',')
  const currentHost = location.protocol + '//' + location.host
  const isCurrentHost = (url: string) => url.includes(currentHost)
  const newUrls = {
    redirectSignIn: urlsIn.find(url => isCurrentHost(url)),
    redirectSignOut: urlsOut.find(url => isCurrentHost(url))
  }
  Amplify.configure({
    ...awsconfig,
    oauth: {
      ...awsconfig.oauth,
      ...newUrls
    }
  })
}

Then you can call the configureAmplify in your App

Cognito & Amplify should either not allow setting more than one URL, or they should handle it properly.

When you set more than one domain/URL, it could link to some documentation and this can have consequences. Imagine this happening for an app on production when they add another URL, and debugging this can be hard as this is not documented in the right way.

My Preview build fails with a redirect mismatch error, because it doesn’t update auth with the preview url. I don’t understand how Amplify doesn’t do this automatically. How do you update sign-in/sign-out redirect URIs headlessly?

Remember to add your redirect url to the facebook developer dashboard https://YOUR-DOMAIN.auth.us-east-1.amazoncognito.com/oauth2/idpresponse