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.36k stars 2.1k forks source link

V6 - Not be able to sign in automatically with Federation #13306

Closed Deanfei closed 2 weeks ago

Deanfei commented 2 weeks ago

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

Authentication

Amplify Version

v6

Amplify Categories

auth

Backend

Amplify Gen 2 (Preview)

Environment information

``` # Put output below this line System: OS: macOS 14.4 CPU: (10) arm64 Apple M1 Pro Memory: 12.42 GB / 32.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 20.6.1 - ~/.nvm/versions/node/v20.6.1/bin/node Yarn: 1.22.19 - ~/.nvm/versions/node/v20.6.1/bin/yarn npm: 9.8.1 - ~/.nvm/versions/node/v20.6.1/bin/npm pnpm: 8.10.0 - ~/.nvm/versions/node/v20.6.1/bin/pnpm Watchman: 2024.04.08.00 - /opt/homebrew/bin/watchman Browsers: Chrome: 124.0.6367.92 Edge: 122.0.2365.80 Safari: 17.4 npmPackages: @aws-amplify/auth: ^6.2.1 => 6.2.1 @aws-amplify/auth/cognito: undefined () @aws-amplify/auth/cognito/server: undefined () @aws-amplify/auth/enable-oauth-listener: undefined () @aws-amplify/auth/server: undefined () @babel/plugin-proposal-private-property-in-object: ^7.21.11 => 7.21.11 (7.21.0-placeholder-for-preset-env.2) @emotion/cache: ^11.9.3 => 11.11.0 @emotion/react: ^11.9.3 => 11.11.4 @emotion/styled: ^11.9.3 => 11.11.5 @mui/icons-material: ^5.8.4 => 5.15.15 @mui/lab: ^5.0.0-alpha.88 => 5.0.0-alpha.170 @mui/material: ^5.8.6 => 5.15.15 @mui/system: ^5.8.6 => 5.15.15 @mui/utils: ^5.8.6 => 5.15.14 @types/jest: ^27.0.1 => 27.5.2 @types/node: ^16.7.13 => 16.18.96 (20.12.7) @types/react: ^18.0.0 => 18.2.79 @types/react-dom: ^18.0.0 => 18.2.25 @typescript-eslint/eslint-plugin: ^5.0.0 => 5.62.0 aws-amplify: ^6.1.4 => 6.1.4 aws-amplify/adapter-core: undefined () aws-amplify/analytics: undefined () aws-amplify/analytics/kinesis: undefined () aws-amplify/analytics/kinesis-firehose: undefined () aws-amplify/analytics/personalize: undefined () aws-amplify/analytics/pinpoint: undefined () aws-amplify/api: undefined () aws-amplify/api/server: undefined () aws-amplify/auth: undefined () aws-amplify/auth/cognito: undefined () aws-amplify/auth/cognito/server: undefined () aws-amplify/auth/enable-oauth-listener: undefined () aws-amplify/auth/server: undefined () aws-amplify/data: undefined () aws-amplify/data/server: undefined () aws-amplify/datastore: undefined () aws-amplify/in-app-messaging: undefined () aws-amplify/in-app-messaging/pinpoint: undefined () aws-amplify/push-notifications: undefined () aws-amplify/push-notifications/pinpoint: undefined () aws-amplify/storage: undefined () aws-amplify/storage/s3: undefined () aws-amplify/storage/s3/server: undefined () aws-amplify/storage/server: undefined () aws-amplify/utils: undefined () docx: ^8.0.4 => 8.5.0 eslint: ^8.0.1 => 8.57.0 eslint-config-prettier: ^8.6.0 => 8.10.0 eslint-config-standard-with-typescript: ^26.0.0 => 26.0.0 eslint-plugin-i18next: ^6.0.0-2 => 6.0.3 eslint-plugin-n: ^15.0.0 => 15.7.0 eslint-plugin-prettier: ^4.2.1 => 4.2.1 eslint-plugin-promise: ^6.0.0 => 6.1.1 eslint-plugin-react: ^7.31.11 => 7.34.1 formik: ^2.2.9 => 2.4.5 i18next: ^22.4.10 => 22.5.1 moment: ^2.29.4 => 2.30.1 mui-file-dropzone: ^4.0.2 => 4.0.2 notistack: ^3.0.1 => 3.0.1 prettier: ^2.8.1 => 2.8.8 react: ^18.2.0 => 18.2.0 react-device-detect: ^2.2.2 => 2.2.3 react-dom: ^18.2.0 => 18.2.0 react-i18next: ^12.1.5 => 12.3.1 react-image-file-resizer: ^0.4.8 => 0.4.8 react-markdown: ^8.0.5 => 8.0.7 react-perfect-scrollbar: ^1.5.8 => 1.5.8 react-router: 6.3.0 => 6.3.0 react-router-dom: 6.3.0 => 6.3.0 react-scripts: ^5.0.1 => 5.0.1 react-syntax-highlighter: ^15.5.0 => 15.5.0 rehype-raw: ^6.1.1 => 6.1.1 remark-gfm: ^3.0.1 => 3.0.1 source-map-explorer: ^2.5.3 => 2.5.3 tesseract.js: ^5.0.5 => 5.0.5 typescript: ^4.9.5 => 4.9.5 uuid: ^9.0.0 => 9.0.1 (8.3.2) yet-another-react-lightbox: ^3.5.3 => 3.17.3 yup: ^0.32.11 => 0.32.11 npmGlobalPackages: @aws-amplify/cli: 12.11.0 @nestjs/cli: 10.3.2 corepack: 0.15.3 npm: 9.8.1 ```

Describe the bug

As suggested by AWS in the V6 migration from V5, I now use the following code for federation signin as:

 await signInWithRedirect({
                provider: 'Google',
              });

However, the browser always stuck on the step xxx.com?code=xxx&state=xxx and not proceeded anymore. After debugging on the source code, and I found that it could be caused by this piece of code: https://github.com/aws-amplify/amplify-js/blob/main/packages/auth/src/providers/cognito/apis/signInWithRedirect.ts#L119C1-L122C6

As the comment says it's only resolves on the react native but not the browser. But I assume it's shared with the react version? I am currently using aws-amplify/auth for my react application, should I use a different package?

Expected behavior

when signed in with federation, the code should automatically handle the code and state to exchange new tokens.

Reproduction steps

  1. create a new react application
  2. install the aws-amplify and aws-amplify/auth packages
  3. configure auth and Google sign in
  4. sign in with Google

Code Snippet

 <Button

            onClick={async () => {
              await signInWithRedirect({
                provider: 'Google',
              });
            }}

          >
            {t('Sign in with Google')}
          </Button>

Log output

``` // Put your logs below this line ```

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

israx commented 2 weeks ago

Hello @Deanfei. How does your oauth config look like ? Also make sure you are importing the signInWithRedirect API as follows,

import { signInWithRedirect } from 'aws-amplify/auth';

Can you also listen for the following hub events and see if you get any logs?

Hub.listen("auth", ({ payload }) => {
      switch (payload.event) {
        case "signInWithRedirect":
          console.log('signInWithRedirect event');
          break;
        case "signInWithRedirect_failure":
         console.log('signInWithRedirect_failure event', payload.data);
          break;
      }
    });

Finally, if nothing from above worked. Can you also downgrade the version of amplify to 6.0.27 and see if the issue persists ?

Deanfei commented 2 weeks ago

I did imported from import { signInWithRedirect } from 'aws-amplify/auth';. I just upgraded from 6.0.27 to the latest because neither works.

The oauth config is correct. I believe the problem is due to this piece of code https://github.com/aws-amplify/amplify-js/blob/main/packages/auth/src/providers/cognito/apis/signInWithRedirect.ts#L119C1-L122C6

In javascript, this function won't return {type, error, url} at all. export const openAuthSession: OpenAuthSession = async (url: string) => { if (!window?.location) { return; } // enforce HTTPS window.location.href = url.replace('http://', 'https://'); };

The Hub events won't be triggered as it's part of the completion oauth flow https://github.com/aws-amplify/amplify-js/blob/main/packages/auth/src/providers/cognito/apis/signInWithRedirect.ts#L120-L137. The code stuck there. I assume it's an obvious bug there.

israx commented 2 weeks ago

Hello @Deanfei . The code above you describe will be compiled into RN only. Web applications will behave different. Is it possible for you to provide a sample app so we can try reproducing this issue ?

Deanfei commented 2 weeks ago

Sorry, I don't have a sample app on hand. When I debug the code in the node_module of the browsers, it did reached to the code I attached. I don't understand how come it's only be compiled into RN but actually run in the browser in my react app?

I am wondering would your team like have a public repo that have the react SSO working so that we can have a reference?

israx commented 2 weeks ago

I see you are using pnpm as the package manager. Can you switch to npm or yarn and see if you still see the code you pointed bundled in the node_modules ?

Deanfei commented 2 weeks ago

Hi @israx Very appreciated your quick response and support. I did use npm or yarn for my project. pnpm is for something else.

l eventually made it working. That's due to my signin page is lazy loaded. When I did a eager bundling with the main app. Everything just worked magically...😔 This is the code I used (just removed it fixed the issue).

const SignIn = Loadable(
  lazy(async () => import('../../components/views/authentication/SignIn')),
);

I am not sure if it's reproducible on a brand new project or not and why. However, I generally felt the Amplify V6 has some problem internally. I got the exact same code with V5 which works perfectly.

I'll close this issue as I hope our Amplify could fix that in a future version. Thanks again.

jojimcNova commented 2 weeks ago

I have the same issue with the signInWithRedirect, this is the code :

` const response = await signInWithRedirect({provider: { custom: 'custom-idp' }});

const { username, userId, signInDetails } = await getCurrentUser();
if(signInDetails?.loginId) {
  console.log('Login !')
  console.log(`The username: ${signInDetails.loginId}`);
  router.push('/');
}

`

my response is the following : http://localhost:3000/?code=[Authorization_code]&state=[State_code]

I'm currently using npm and I'm at version "aws-amplify": "^6.2.0"

It doesn't login, and there is nothing present in the cookies

I'm trying to follow the current thread, available if you need more information.

Thanks

cwomack commented 2 weeks ago

@Deanfei, glad to hear you're unblocked!

@jojimcNova, is this a new v6 app or one that you upgraded from v5? And could you share what your signInDetails code looks like?

jojimcNova commented 2 weeks ago

Hi @cwomack ,

Yes it's a brand new project I created. I'm using NextJs, and I want to add a custom login page, where the user can login with credentials (signIn), which currently works correctly, and via signInWithRedirect which I have this issue.

I don't have any signInDetails because the response I receive from my signInWithRedirect is undefined

israx commented 2 weeks ago

hello @jojimcNova . Can you add the following code into the page you are redirected to from your social provider.

import 'aws-amplify/auth/enable-oauth-listener';

This will allow the signInWithRedirect to complete the authentication flow in multipage applications.

For more info check this doc section

jojimcNova commented 2 weeks ago

Hi @israx, I added the suggested import, and there is no difference. The return value is still the same as follow : image

After I'm redirected to the login page like nothing happened. When I try to console.log the answer of the signInWithRedirect, it is undefined. I'm about to handle it manually, but maybe I can get some answer with you before starting.

Thanks

Deanfei commented 2 weeks ago

I would say the hub won't emit any events since they are part of the completion oauth flow. At this stage, the amplify should exchange access tokens with the code and state here. If it stuck here, that means we are not logged in yet.

When you see the cookies from the cognito stored in the localstorage (or session storage depends on your own config), that means we succeeded the signin.

israx commented 2 weeks ago

@jojimcNova can you make sure to ?

  1. call signInWithRedirect from the client
  2. to enable the ssr flag in the amplify configuration
jojimcNova commented 2 weeks ago

Hi @israx , yes this is what I did :

1 - I have a login form with credentials and a custom provider. The credential way works properly, but the signInWithRedirect is called from the client side. const response = await signInWithRedirect({provider: { custom: 'custom-idp' }});

2 - Yes, the ssr flag is enable. I have it setup in the layout as follow :

"use client";

import config from "@/awsconfig";
import { Amplify } from "aws-amplify";

Amplify.configure(config, { ssr: true });

export default function ConfigureAmplifyClientSide() {
  return null;
}

and in the layout, it is setup as follow :

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <ThemeRegistry>
        <body>
          <ConfigureAmplifyClientSide />
          {children}
        </body>
      </ThemeRegistry>
    </html>
  );
}

By the way, when importing the import 'aws-amplify/auth/enable-oauth-listener'; when I tried to go in the function, it looks like it's empty : export {};

Is it normal ?

israx commented 2 weeks ago

@jojimcNova yeah the import 'aws-amplify/auth/enable-oauth-listener'; is used to enable a side effect only. Just to confirm, after doing all of above you are still getting the code and state params hanging on your URL, right ? Something to clarify is that the signInWithRedirect API doesn't resolve to a value. You would need to listen for the signIWithRedirect or signInWithRedirect_failure hub events.

israx commented 2 weeks ago

Also if the issue still persists, could you please open a new GH issue describing reproduction steps ? So we can assist you better.

jojimcNova commented 2 weeks ago

Hi @israx,

I've tried with the Hub, there is no response. I opened a GH issue : https://github.com/aws-amplify/amplify-js/issues/13332