aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.12k forks source link

Can't use "code" as a query parameter #3494

Closed cliffordh closed 1 year ago

cliffordh commented 5 years ago

Using the query parameter name "code" causes "invalid_grant" error due to the Amplify listener attempting to validate the parameter as an OAuth code. Might make sense to namespace the code parameter to "awscode" or even validate that the code value looks like an OAuth response code before throwing an error.... took a few hours to debug this.

jessedoyle commented 5 years ago

I can absolutely second this - Amplify completely highjacks the code parameter if present via form post or URL queries.

This caught us off guard a while back and required significant troubleshooting as the error message is vague and seems unrelated.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

jaimeburnap-fts commented 4 years ago

Any updates on this?

danielblignaut commented 4 years ago

+1

jonmifsud commented 4 years ago

Does anyone have a workaround? We need to use some oAuth 2.0 third party verification and this really messes up the experience :(

clethrill commented 4 years ago

This is extremely irritating, implementing third party oAuth2 integration and when it redirects back to my site it errors out assuming it's the SSO code.

Would simply changing line 128 of OAuth.ts to something like if (!code || currentUrl !== this._config.redirectSignIn) fix the issue? Then it wouldn't highjack if you were at /oauth2integration/callback?code=xxx

swyxio commented 4 years ago

@clethrill good suggestion and deep sympathies for the frustration caused.

@sammartinez would suggest bumping this up to a bugbash considering the fix may be a oneliner

clethrill commented 4 years ago

I created a PR #6939 to try and help speed things along.

SandonAhoy commented 3 years ago

Pr doesn't look like it's fixed the issue, I also get the issue using the query string 'error' as well as the original issue with 'code' if I go anywhere on my site like mysite.com/path/to/somewhere?error aws-amplify will log me out with a console message saying I've had an OAuth error. This seems like a pretty major issue, I don't know how no one else has run into this? Surely someone using aws-amplify has at some point tried to put ?error into their website?

harryrein3 commented 3 years ago

I saw this specifically with the Instagram Basic Display API where they attempt to use the code parameter and amplify steals it and throws an invalid user pool error. I can catch it beforehand and change the URL to use insta_code instead of code, but that requires another page load. Could we just allow this URL param to be configured?

DevNM21-zz commented 3 years ago

A workaround for this would to be add rewrites in your amplify's settings. Something like this perhaps: Screenshot_2021-05-23_12-34-42 Mine was next.js application and it worked fine.

oferitz commented 3 years ago

Any updates? This is really annoying. We have a workaround that feels very hacky, as we had to catch the url search params at a very early point in the app, check if there is a param with the name code, replace it with our name and then reload the app.

It seems like @clethrill PR (#6939) didn't solve the issue and @Khairo-kh PR (#8589) is stuck. So I kindly ask the maintainers to try and help here, Amplify should not highjack the code parameter, this is just wrong.

ff-randy commented 2 years ago

Any updates? I'm having the issue trying to integrate with a third party service that redirect to our site and appends the parameter "code".

SandonAhoy commented 2 years ago

@DevNM21-zz workaround works, I've also implemented something similar

renderProps.location.search = renderProps.location.search.replace('?code', '?xcode').replace('?error', '?xerror')
window.location.replace(`${renderProps.location.pathname}${renderProps.location.search.replace('?code', '?xcode').replace('?error', '?xerror')}`)
return <Redirect to={`${renderProps.location.pathname}${renderProps.location.search.replace('?code', '?xcode').replace('?error', '?xerror')}`} />

Interestingly I do not get the issue in another project where I have more of a custom implementation of Auth.

AG-Labs commented 2 years ago

Any succeed with this with a react app. Redirects aren't working and I don't fancy reloading the app.

AG-Labs commented 2 years ago

I have had a look through the code and it seems like the change made in https://github.com/aws-amplify/amplify-js/pull/6939 was the right check but it happened too low down the chain of calls. would making a change here solve the issue? https://github.com/aws-amplify/amplify-js/blob/main/packages/auth/src/Auth.ts#L2053

could be changed to

if ((hasCodeOrError || hasTokenOrError) &&
    (this._config.oauth as AwsCognitoOAuthOpts).redirectSignIn ===
    parse(currentUrl).pathname ) {

EDIT I have made a PR with changes that I think are correct based on the two above PRs that are linked in this issue. I have not yet run this locally, if anyone is able to help with that that would be great.

tills13 commented 2 years ago

If anyone is still waiting for the fix for this to land, I have a solution in the interim. This works for tools and hosting platforms that allow multiple HTML entrypoints. In my case, I'm using Vite + CloudFlare pages. I will add some tool-specific code here... be warned 😆

Create another html entrypoint in your app. I chose oauth_callback.html. The contents of this file are

<html>
    <head>
        <script>
            const queryParams = new URLSearchParams(location.search);
            // I handle my oauth at http://example.com/oauth/callback
            const realOAuthCallbackUrl =
                window.location.protocol +
                "//" +
                window.location.host +
                "/" +
                "oauth/callback";

            // capture the code and state from the URL
            const code = queryParams.get("code");
            const state = queryParams.get("state");

            // make a URLSearchParams for formatting convenience
            // renaming code and state in the process
            const newParams = new URLSearchParams({
                // code becomes oauth_code
                oauth_code: code,
                // state become oauth_state
                oauth_state: state,
            });

            // redirect to your actual callback 
            window.location = realOAuthCallbackUrl + "?" + newParams.toString();
        </script>
    </head>
</html>

In GCP, I've added https://example.com/oauth_callback.html as an allowed callback and I use this as the redirect_uri in the original request to the federation endpoint.

Remember to read these values from their mapped params not the old params.

For Vite, I added this page to the build (+ dev server) by adding the following to my vite.config.ts

export default defineConfig({
    build: {
        rollupOptions: {
            input: {
                main: path.resolve(__dirname, "index.html"),
                oauth_callback: path.resolve(__dirname, "oauth_callback.html"),
            },
        },
    },
});
tannerabread commented 1 year ago

Closing this as a duplicate of #10415. We will be tracking the progress on the more recent issue

tannerabread commented 1 year ago

Update: there were 2 duplicates, tracking progress on #9208 as it has the most context and attached PRs