amplify-cli
amplify-cli copied to clipboard
[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:
- setup amplify with user pools and facebook identity provider
- create a new next ts project
- import amplify newest version:
import { Auth } from 'aws-amplify'; import { CognitoHostedUIIdentityProvider } from "@aws-amplify/auth/lib/types";- Call
Auth.federatedSignIn({provider: CognitoHostedUIIdentityProvider.Facebook}); - 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-exportsfile:
- If applicable, please provide your
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.
How about use @aws-amplify/Auth. The way I see it, there is no export CognitoHostedUIIdentityProvider with aws-amplify library. But It works with @aws-amplify/Auth.
import { CognitoHostedUIIdentityProvider } from '@aws-amplify/auth'
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';
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]"}
Still have this issue, is this because I'm using Next.js? The call to /login works as expected, and I'm redirected to my post-login page. However after this, next removes the trailing slash:
308 Permanent Redirect - example.com/dashboard/?code=xxxxxxxx&state=xxxxxx 200 OK - example.com/dashboard?code=xxxxxxxx&state=xxxxxx
After this amplify should be calling cognito-auth-url.com/oauth2/token to get the auth token. But this call is never made. Instead it calls cognito-identity.us-east-2.amazonaws.com with a botched login because the auth token it was supposed to get from the other call was never made
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
How is this still open
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
Any update or workaround on this? Really struggling on this one - Next JS / Typescript / Amplify
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.
jarrodwatts@ Thats what I had to do as well.
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 :D
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!
Adding trailing slash seems to cause problem with amplify hosting. Getting a redirect loop and rewrites with %2F instead of slashes. So +1 to get this fixed.
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".
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 about this? I'm having the same issue as @aj120426394, tried his solution but still the problem persist.
note: potentially need to handle trailing slashes in libraries as well
Any update on this?
fyi: redirecting to http://localhost:8000/foo resulted in a redirect loop, but redirecting to http://localhost:8000 stopped the redirect loop and made auth work as expected.
I'm using nextjs, using Amplify.configure(), and manually specifying the configuration object.
Any solution?
Wasted many hours on this. Turns out there are various things that can break it, trailing slashes, custom domains, etc. aws-exports.js will have oauth configuration generated on amplify push from your cli inputs. That configuration will often have the "wrong" settings (for example, point to a cognito domain when you have a custom one, or have the wrong redirect urls). These things end up with a request to cognito with an incomplete payload (blank login).
In my case there were a few things needed:
- Be consistent with trailing slashes on my main.js, aws-exports.js and my auth configuration passed on to Auth.configure()
- have a completely separate configuration for Auth, not rely on aws-exports.js, something like this:
import awsconfig from './aws-exports';
import awsauth from './aws-auth';
awsconfig.oauth={} // ignore the aws-exports auth settings
Amplify.configure(awsconfig);
awsauth.oauth.redirectSignIn = `${window.location.origin}/`;
awsauth.oauth.redirectSignOut = `${window.location.origin}/`;
const currentConfig = Auth.configure(awsauth);
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?
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
openidin my scopes.const awsconfig = { Auth: { ... oauth: { ... scope: ['email', 'aws.cognito.signin.user.admin', 'profile', 'openid'], ... }, }, };When the
codeFlowauth event happens on the client, it goes to retrieve tokens from your auth providerhttps://xxxxxx/oauth2/token. If you don't includeopenidin your scopes, you won't get anid_tokenback. 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_tokenis a JWT that is then used to fill inLoginsin the request. Without thatid_token, you get the problem listed above: "THIS IS BLANK AND IT SHOULDN'T BE".
You are a hero.
+1
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.
This worked for me locally
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.
@jarrodwatts This is what was missing for me 🙏🏽. Thank you for offering this solution Can't believe this is still an issue
This issue is still persistent, insane how this is not fixed...... devs do something please, or at least give a heads up about this issue.
Spent 1 week troubleshooting this issue to figure out it doesn't accept "/"
while logging sso (Google) that was successful. but after redirecting to my URI it throws an error. that error was ( Uncaught (in promise) Error: No current user ). and in a network, the error was --->
[ {"__type":"ValidationException","message":"1 validation error detected: Value '{cognito-idp.ap-south-1.amazonaws.com/ap-south-1_ibkjGZP3L=}' 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]"} ]
how do resolve this @Neuroforge ?
Hi guys,
I got the same issue,
I think the reason for this error is that the URL redirect and the url (redirectSignIn, redirectSignOut) we configured in Amplify.configure do not match, even the '/' character.
yes, trailingSlash: true can be useful, but it may not be necessary if we have configured the redirect url as aws user pool and ours env are same even the '/'.
In my case, my website supports internationalization, but I configure redirectSignIn and redirectSignOut in Amplify.configure incorrect.
Here's my solution: add this code in RootLayout or AppProvider or some where like that
const updatedAwsConfig = {
...awsConfig,
oauth: {
...awsConfig.oauth,
redirectSignIn:
locale === DEFAULT_LOCALE
? `${process.env.BASE_URL}/${your-page-name}`
: `${process.env.BASE_URL}/${locale}/${your-page-name}`,
redirectSignOut:
locale === DEFAULT_LOCALE
? `${process.env.BASE_URL}`
: `${process.env.BASE_URL}/${locale}`,
},
}
Amplify.configure(updatedAwsConfig)
I hope this helps someone
I still have this issue.