amplify-cli: [Exact Line Found] Amplify Auth doesn't work for non-trailing slash redirect

Adding up here for visibility:

Found the bug: https://github.com/aws-amplify/amplify-js/blob/286c9e8fbec3ccdc5bf24edf3cbfb2bae370d751/packages/auth/src/OAuth/OAuth.ts#L128-L130

Please update this to not care about a trailing slash.

example.com/dashboard/?code=xxxxxxxx&state=xxxxxx == example.com/dashboard?code=xxxxxxxx&state=xxxxxx

Amplify shouldn’t care about trailing slash, this line needs to be updated to disregard trailing slash from redirect url.

Describe the bug I’m able to sign in with Auth.federatedSignIn({provider: 'Facebook'}); in js, but I can’t use that in typescript. Auth.federatedSignIn({provider: CognitoHostedUIIdentityProvider.Facebook}) fails because it calls cognito-identity instead of cognito-idp. My local storage isn’t updated with the cognito tokens and I get a 400 from cognito-identity.us-east-1.amazonaws.com. js does not call this endpoint ever, not sure why the ts SDK is calling it, or why there is no user-pool support for this. my export file is the same for both js and ts. The only difference is the federated sign in call above.

To Reproduce Steps to reproduce the behavior:

  1. setup amplify with user pools and facebook identity provider
  2. create a new next ts project
  3. import amplify newest version: import { Auth } from 'aws-amplify';
  4. import { CognitoHostedUIIdentityProvider } from "@aws-amplify/auth/lib/types";
  5. Call Auth.federatedSignIn({provider: CognitoHostedUIIdentityProvider.Facebook});
  6. Open your network tab in chrome and see that cognito-identity is being called. even though the aws-export file should have "federationTarget": "COGNITO_USER_POOLS"

eg:

import React from "react";
import { Button, Heading } from "@chakra-ui/react";

import { CognitoHostedUIIdentityProvider } from "@aws-amplify/auth/lib/types";
import { Auth } from 'aws-amplify';

interface loginProps {}

export const Login: React.FC<loginProps> = ({}) => {

  function continueWithFacebook() {
    return Auth.federatedSignIn({provider: CognitoHostedUIIdentityProvider.Facebook});
  }

  return (
    <div>
      <Button onClick={() => continueWithFacebook()}>Continue with Facebook</Button>
    </div>
  );
};

export default Login;

This is the call from the typescript sdk. Notice its missing the login:

{"IdentityId":"us-east-1:xxx","Logins":{"cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxx":"<THIS IS BLANK AND SHOULDN'T BE>"}}

Expected behavior The vanilla js version of this works. Auth.federatedSignIn({provider: 'Facebook'}); works as expected. You can go to the application tab in chrome and see local storage updated. CognitoIdentityServiceProvider object will be under the local storage tab.

cognito-identity.us-east-1.amazonaws.com is called with a valid login.

{"IdentityId":"us-east-1:xxx","Logins":{"cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxx":"eyJraWQiOiJWTzYrsasfasdf"}}

Code Snippet Please provide a code snippet or a link to sample code of the issue you are experiencing to help us reproduce the issue. (Be sure to remove any sensitive data)

Working: Auth.federatedSignIn({provider: 'Facebook'}); in js Not working: Auth.federatedSignIn({provider: CognitoHostedUIIdentityProvider.Facebook}) in tsx

What is Configured? If applicable, please provide what is configured for Amplify CLI:

  • Which steps did you follow via Amplify CLI when configuring your resources.
  • Which resources do you have configured?
    • If applicable, please provide your aws-exports file:

const awsmobile = { “aws_project_region”: “us-east-1”, “aws_cognito_identity_pool_id”: “us-east-1:xxx”, “aws_cognito_region”: “us-east-1”, “aws_user_pools_id”: “us-east-1_xxx”, “aws_user_pools_web_client_id”: “xxx”, “oauth”: { “domain”: “homulator-auth-dev.auth.us-east-1.amazoncognito.com”, “scope”: [ “phone”, “email”, “openid”, “profile”, “aws.cognito.signin.user.admin” ], “redirectSignIn”: “http://localhost:3000/dashboard/”, “redirectSignOut”: “http://localhost:3000/”, “responseType”: “code” }, “federationTarget”: “COGNITO_USER_POOLS” };

  • If applicable, provide more configuration data, for example for Amazon Cognito, run aws cognito-idp describe-user-pool --user-pool-id us-west-2_xxxxxx (Be sure to remove any sensitive data)
Environment
npx envinfo --system --binaries --browsers --npmPackages --npmGlobalPackages

Smartphone (please complete the following information):

  • Browser Chrome

Additional context Add any other context about the problem here.

You can turn on the debug mode to provide more info for us by setting window.LOG_LEVEL = ‘DEBUG’; in your app.

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 7
  • Comments: 30 (2 by maintainers)

Most upvoted comments

Anyone finding this thread, an easy hack solution if you are using Next JS, is to include: trailingSlash: true, in your next.config.js file. Sucks this has to be done, but easy work around for the time being.

I had this same issue, but the root cause was not a trailing slash. There is no problem with the library, I had a misconfiguration on the app and the server.

Problem: {"IdentityId":"us-east-1:xxx","Logins":{"cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxx":"<THIS IS BLANK AND SHOULDN'T BE>"}}

I solved it by including openid in my scopes.

const awsconfig = {
  Auth: {
    ...
    oauth: {
        ...
        scope: ['email', 'aws.cognito.signin.user.admin', 'profile', 'openid'],
        ...
    },
  },
};

When the codeFlow auth event happens on the client, it goes to retrieve tokens from your auth provider https://xxxxxx/oauth2/token. If you don’t include openid in your scopes, you won’t get an id_token back. These docs say “Note that an ID token is only provided if the openid scope was requested”: https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-user-pool-oauth-2-0-grants/

That id_token is a JWT that is then used to fill in Logins in the request. Without that id_token, you get the problem listed above: “THIS IS BLANK AND IT SHOULDN’T BE”.

How is this still open

Found the bug: https://github.com/aws-amplify/amplify-js/blob/286c9e8fbec3ccdc5bf24edf3cbfb2bae370d751/packages/auth/src/OAuth/OAuth.ts#L128-L130

Please update this to not care about a trailing slash. Or at the very least do not fail silently, makes no sense why this is a blank return. The auth flow half succeeds then just fails randomly.

example.com/dashboard/?code=xxxxxxxx&state=xxxxxx == example.com/dashboard?code=xxxxxxxx&state=xxxxxx

I’m experiencing the same issue with the typescript sdk and nextjs. The auth flow only works, if my redirect sign-url is http://localhost:3000. When I’m changing it to http://localhost:3000/sign-in it fails with the mentioned 400 error

I ran into this problem today. After few hours of try and error, for people who have the same issue maybe you can try this solution.

I crated an OIDC idp via AWS Cognito console manually. It was working when I manually add OAuth config in index.js like this:

Amplify.configure(aws_exports)
Auth.configure({
  ...aws_exports,
  oauth: {
    domain: 'xxxxxx-dev.auth.ap-southeast-2.amazoncognito.com',
    scope: ['openid'],
    redirectSignIn: 'http://localhost:3000/,http://localhost:3000/xxxx/,https://xxxxx/yyyyyyy/',
    redirectSignOut: 'http://localhost:3000/,http://localhost:3000/xxxx/,https://xxxxx/yyyyyyy/',
    responseType: 'code'
  }
})

However, we have multiple backend environment. We decide to setup OAuth config via amplify-cli to allow the domain be dynamic. Then it went into the problem above. The solution I finally came with is:

Amplify.configure({ ...aws_exports, oauth: undefined })
Auth.configure({
  ...aws_exports,
  oauth: {
    ...aws_exports.oauth,
    redirectSignIn: `${window.location.origin}/`,
    redirectSignOut: `${window.location.origin}/`
  }
})

So far, I have no idea why this works. Seems like Amplify.configure() doesn’t like oauth, and you need to set if via Auth.configure(). Also redirectSignIn and redirectSignOut only accept single url. It used to (before config via cli) accept multiple url.

Hope this could help someone.

Any updates on this?

I was able to resolve this issue with Next.js using trailingSlash: true config as suggested by @jarrodwatts

This seemed great until we realized trailing slashes broke our blog.

The blog is a separate Next.js codebase which we link to the main webpage with Next.js rewrites - but we can’t override the trailingSlash behavior local to the blog itself - it is enforced across the entire domain.

It looks like we have to choose between OAuth or our blog. Unless someone pushes a fix 😃

It seems like Vercel has been sitting on this issue for a couple years now.

Has anyone else run into a similar situation and worked around it?

Any updates about this? I’m having the same issue as @aj120426394, tried his solution but still the problem persist.

I ran into the below error last night, and my redirect did not contain a trailing slash.

validation error detected: Value '{cognito-idp.us-east-1.amazonaws.com/us-east-xxx=}' at 'logins' failed to satisfy constraint: Map value must satisfy constraint: [Member must have length less than or equal to 50000, Member must have length greater than or equal to 1]"}

My issue was that I needed to add responseType: 'code' to the Amplify oauth configuration object.

My Amplify configuration:

const awsconfig = {
  Auth: {
    userPoolId: 'us-east-1_x',xxx
    userPoolWebClientId: 'xxx',
    identityPoolId: 'us-east-1:xxx',
    region: 'us-east-1',
    oauth: {
      domain: 'xxx.auth.us-east-1.amazoncognito.com',
      redirectSignIn: redirectUri,
      redirectSignOut: redirectUri,
      responseType: 'code',
      urlOpener,
    },
  },
};

What helped me figure out the exact problem was adding window.LOG_LEVEL = 'DEBUG'; and I was able to get the following message:

[DEBUG] 57:07.955 OAuth - Starting undefined flow with exp://127.0.0.1:19000?code=xxx

Hope this helps someone!

I am facing this exact issue in my project. Hopefully they fix it fast. @jarrodwatts Thanks for the soln. for now. Saved me a lot of time 😄

I deleted and re-set up my amplify auth, its still calling https://cognito-identity.us-east-1.amazonaws.com/ with an empty login:

See below request that I copied from chrome as a fetch

fetch("https://cognito-identity.us-east-1.amazonaws.com/", {
  "headers": {
    "accept": "*/*",
    "accept-language": "en-US,en;q=0.9",
    "amz-sdk-invocation-id": "0a1356f1-3c72-443f-819c-686149132528",
    "amz-sdk-request": "attempt=1; max=3",
    "content-type": "application/x-amz-json-1.1",
    "sec-ch-ua": "\"Google Chrome\";v=\"87\", \" Not;A Brand\";v=\"99\", \"Chromium\";v=\"87\"",
    "sec-ch-ua-mobile": "?0",
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "cross-site",
    "x-amz-target": "AWSCognitoIdentityService.GetId",
    "x-amz-user-agent": "aws-sdk-js-v3-@aws-sdk/client-cognito-identity/1.0.0-rc.4 Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 aws-amplify/3.8.7 js"
  },
  "referrer": "http://localhost:3000/",
  "referrerPolicy": "strict-origin-when-cross-origin",
  "body": "{\"IdentityPoolId\":\"us-east-1:xxxxxxxxxxxxxxxxxxxxxxxxxxx\",\"Logins\":{\"cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxx\":\"\"}}",
  "method": "POST",
  "mode": "cors"
});
{"__type":"ValidationException","message":"1 validation error detected: Value '{cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxx=}' at 'logins' failed to satisfy constraint: Map value must satisfy constraint: [Member must have length less than or equal to 50000, Member must have length greater than or equal to 1]"}

Sorry I should have been more specific, I’ll update my comment. I’m using

import { CognitoHostedUIIdentityProvider } from "@aws-amplify/auth/lib/types";
import { Auth } from 'aws-amplify';