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.44k stars 2.13k forks source link

Unable to set Cookies for Social Login (Google) #13571

Closed ulisescarreonalvarez closed 4 months ago

ulisescarreonalvarez commented 4 months ago

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

Authentication

Amplify Version

v6

Amplify Categories

auth

Backend

Other

Environment information

``` # Put output below this line System: OS: Windows 11 10.0.22631 CPU: (20) x64 13th Gen Intel(R) Core(TM) i5-13600KF Memory: 7.60 GB / 63.84 GB Binaries: Node: 20.14.0 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.4 - C:\Program Files (x86)\Yarn\bin\yarn.CMD npm: 10.5.2 - ~\Sites\prestazione\node_modules\.bin\npm.CMD Browsers: Edge: Chromium (126.0.2592.87) Internet Explorer: 11.0.22621.3527 npmPackages: @ant-design/colors: ^7.0.0 => 7.0.2 @ant-design/icons: ^5.3.0 => 5.3.6 (5.3.7) @antv/x6: ^2.18.1 => 2.18.1 @antv/x6-plugin-selection: ^2.2.2 => 2.2.2 @antv/x6-react-shape: ^2.2.3 => 2.2.3 @auth0/auth0-spa-js: ^2.1.1 => 2.1.3 @babel/core: ^7.22.10 => 7.24.4 @babel/eslint-parser: ^7.22.10 => 7.24.1 @babel/plugin-proposal-private-property-in-object: ^7.21.11 => 7.21.11 (7.21.0-placeholder-for-preset-env.2) @date-io/date-fns: ^2.17.0 => 2.17.0 @date-io/dayjs: ^2.17.0 => 2.17.0 @date-io/luxon: ^2.17.0 => 2.17.0 @date-io/moment: ^2.17.0 => 2.17.0 @emotion/cache: ^11.11.0 => 11.11.0 @emotion/react: ^11.11.1 => 11.11.4 @emotion/styled: ^11.11.0 => 11.11.5 @fontsource/inter: ^5.0.8 => 5.0.18 @fontsource/poppins: ^5.0.8 => 5.0.14 @fontsource/public-sans: ^5.0.8 => 5.0.18 @fontsource/roboto: ^5.0.8 => 5.0.13 @fullcalendar/common: ^5.11.5 => 5.11.5 @fullcalendar/core: ^6.1.8 => 6.1.11 @fullcalendar/daygrid: ^6.1.8 => 6.1.11 @fullcalendar/interaction: ^6.1.8 => 6.1.11 @fullcalendar/list: ^6.1.8 => 6.1.11 @fullcalendar/react: ^6.1.8 => 6.1.11 @fullcalendar/timegrid: ^6.1.8 => 6.1.11 @fullcalendar/timeline: ^6.1.8 => 6.1.11 @googlemaps/react-wrapper: ^1.1.35 => 1.1.35 @hello-pangea/dnd: ^16.3.0 => 16.6.0 @mapbox/mapbox-gl-style-spec: 14.4.0 @mui/base: ^5.0.0-beta.11 => 5.0.0-beta.40 @mui/icons-material: ^5.15.10 => 5.15.15 @mui/lab: ^5.0.0-alpha.140 => 5.0.0-alpha.170 @mui/material: ^5.14.5 => 5.15.15 @mui/system: ^5.14.5 => 5.15.15 @mui/x-date-pickers: ^6.11.1 => 6.19.9 @mui/x-tree-view: ^7.3.0 => 7.3.0 @react-google-maps/api: ^2.19.3 => 2.19.3 @react-pdf/renderer: ^3.1.12 => 3.4.2 @react-three/csg: ^3.2.0 => 3.2.0 @react-three/drei: 9.97.0 => 9.97.0 @react-three/fiber: 7.0.26 => 7.0.26 @reduxjs/toolkit: ^2.2.5 => 2.2.5 @reduxjs/toolkit-query: 1.0.0 @reduxjs/toolkit-query-react: 1.0.0 @reduxjs/toolkit-react: 1.0.0 @semantic-release/changelog: ^6.0.3 => 6.0.3 @semantic-release/exec: ^6.0.3 => 6.0.3 @semantic-release/git: ^10.0.1 => 10.0.1 @semantic-release/gitlab: ^13.0.2 => 13.0.3 @stripe/react-stripe-js: ^2.7.1 => 2.7.1 @stripe/stripe-js: ^3.4.1 => 3.4.1 @svgr/webpack: ^8.1.0 => 8.1.0 @tanstack/match-sorter-utils: ^8.8.4 => 8.15.1 @tanstack/react-query: ^4.32.6 => 4.36.1 @tanstack/react-table: ^8.9.3 => 8.16.0 @tanstack/react-virtual: ^3.0.0-alpha.0 => 3.4.0 (3.3.0) @types/js-cookie: ^3.0.6 => 3.0.6 @types/three: 0.146.0 => 0.146.0 (0.163.0) @vitejs/plugin-react: ^4.1.0 => 4.2.1 amazon-cognito-identity-js: ^6.3.2 => 6.3.12 amazon-cognito-identity-js/internals: undefined () antd: ^5.18.0 => 5.18.0 apexcharts: 3.41.0 => 3.41.0 autoprefixer: ^10.4.19 => 10.4.19 autosuggest-highlight: ^3.3.4 => 3.3.4 aws-amplify: ^6.3.4 => 6.3.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 () aws-sdk: ^2.1609.0 => 2.1609.0 axios: ^1.4.0 => 1.6.8 big.js: ^6.2.1 => 6.2.1 buffer: ^6.0.3 => 6.0.3 (4.9.2) chance: ^1.1.11 => 1.1.11 crypto-browserify: ^3.12.0 => 3.12.0 crypto-js: ^4.1.1 => 4.2.0 currency.js: ^2.0.4 => 2.0.4 date-fns: ^2.30.0 => 2.30.0 depcheck: ^1.4.7 => 1.4.7 draft-js: ^0.11.7 => 0.11.7 emoji-picker-react: ^4.4.11 => 4.9.2 eslint: ^8.47.0 => 8.57.0 eslint-config-prettier: ^9.0.0 => 9.1.0 eslint-config-react-app: ^7.0.1 => 7.0.1 eslint-plugin-flowtype: ^8.0.3 => 8.0.3 eslint-plugin-import: ^2.28.0 => 2.29.1 eslint-plugin-jsx-a11y: ^6.7.1 => 6.8.0 eslint-plugin-prettier: ^5.0.0 => 5.1.3 eslint-plugin-react: ^7.33.2 => 7.34.1 eslint-plugin-react-hooks: ^4.6.0 => 4.6.0 eslint-plugin-react-refresh: ^0.4.5 => 0.4.6 firebase: ^10.1.0 => 10.11.0 firebase/analytics: undefined () firebase/app: undefined () firebase/app-check: undefined () firebase/auth: undefined () firebase/auth/cordova: undefined () firebase/auth/web-extension: undefined () firebase/compat: undefined () firebase/compat/analytics: undefined () firebase/compat/app: undefined () firebase/compat/app-check: undefined () firebase/compat/auth: undefined () firebase/compat/database: undefined () firebase/compat/firestore: undefined () firebase/compat/functions: undefined () firebase/compat/installations: undefined () firebase/compat/messaging: undefined () firebase/compat/performance: undefined () firebase/compat/remote-config: undefined () firebase/compat/storage: undefined () firebase/database: undefined () firebase/firestore: undefined () firebase/firestore/lite: undefined () firebase/functions: undefined () firebase/installations: undefined () firebase/messaging: undefined () firebase/messaging/sw: undefined () firebase/performance: undefined () firebase/remote-config: undefined () firebase/storage: undefined () formik: ^2.4.3 => 2.4.5 framer-motion: ^10.16.0 => 10.18.0 fuse.js: ^7.0.0 => 7.0.0 history: ^5.3.0 => 5.3.0 html2pdf.js: 0.9.0 => 0.9.0 immutability-helper: ^3.1.1 => 3.1.1 immutable: ^4.3.2 => 4.3.5 (3.7.6) init: ^0.1.2 => 0.1.2 insert-css: ^2.0.0 => 2.0.0 js-cookie: ^3.0.5 => 3.0.5 (2.2.1) jwt-decode: ^4.0.0 => 4.0.0 konva: 9.3.3 => 9.3.3 less: ^4.2.0 => 4.2.0 lodash: ^4.17.21 => 4.17.21 mapbox-gl: ^3.4.0 => 3.4.0 material-react-table: ^2.11.2 => 2.13.0 moment: ^2.30.1 => 2.30.1 mui-file-input: ^4.0.4 => 4.0.4 notistack: ^3.0.1 => 3.0.1 npx: ^10.2.2 => 10.2.2 postcss: ^8.4.38 => 8.4.38 prettier: ^3.0.2 => 3.2.5 process: ^0.11.10 => 0.11.10 prop-types: ^15.8.1 => 15.8.1 react: ^18.2.0 => 18.2.0 react-apexcharts: ^1.4.1 => 1.4.1 react-compare-slider: ^2.2.0 => 2.2.0 react-copy-to-clipboard: ^5.1.0 => 5.1.0 react-csv: ^2.2.2 => 2.2.2 react-device-detect: ^2.2.3 => 2.2.3 react-dnd: ^16.0.1 => 16.0.1 react-dnd-html5-backend: ^16.0.1 => 16.0.1 react-dnd-scrolling: ^1.3.3 => 1.3.7 react-dnd-touch-backend: ^16.0.1 => 16.0.1 react-dom: ^18.2.0 => 18.2.0 react-draft-wysiwyg: ^1.15.0 => 1.15.0 react-draggable: ^4.4.5 => 4.4.6 react-dropzone: ^14.2.3 => 14.2.3 react-error-overlay: 6.0.11 => 6.0.11 react-fast-marquee: ^1.6.0 => 1.6.4 react-google-recaptcha: ^3.1.0 => 3.1.0 react-html-parser: ^2.0.2 => 2.0.2 react-html-parser-demo: 0.0.0 react-image-gallery: ^1.3.0 => 1.3.0 react-infinite-scroll-component: ^6.1.0 => 6.1.0 react-intersection-observer: ^9.5.2 => 9.8.2 react-intl: ^6.4.4 => 6.6.5 react-konva: 18.2.10 => 18.2.10 react-loading-skeleton: ^3.4.0 => 3.4.0 react-map-gl: ^7.1.3 => 7.1.7 react-number-format: ^5.4.0 => 5.4.0 react-organizational-chart: ^2.2.1 => 2.2.1 react-qr-code: ^2.0.12 => 2.0.12 react-quill: ^2.0.0 => 2.0.0 react-redux: ^9.1.1 => 9.1.1 (8.1.3) react-router: ^6.15.0 => 6.22.3 react-router-dom: ^6.15.0 => 6.22.3 react-signature-canvas: ^1.0.6 => 1.0.6 react-slick: ^0.29.0 => 0.29.0 react-spring: 9.7.2 => 9.7.2 react-syntax-highlighter: ^15.5.0 => 15.5.0 react-table-sticky: ^1.1.3 => 1.1.3 react-timer-hook: ^3.0.7 => 3.0.7 react-to-print: ^2.14.13 => 2.15.1 react-window: ^1.8.9 => 1.8.10 react-zoom-pan-pinch: ^3.1.0 => 3.4.4 react18-input-otp: ^1.1.4 => 1.1.4 semantic-release: ^23.0.2 => 23.0.8 simplebar-react: ^3.2.4 => 3.2.4 slick-carousel: ^1.8.1 => 1.8.1 stream-browserify: ^3.0.0 => 3.0.0 stylis-plugin-rtl: ^2.1.1 => 2.1.1 swr: ^2.2.5 => 2.2.5 tailwindcss: ^3.4.3 => 3.4.4 three: 0.143.0 => 0.143.0 three-csg-ts: 3.1.13 => 3.1.13 three-obj-mtl-loader: 1.0.3 => 1.0.3 three-orbitcontrols: 2.110.3 => 2.110.3 use-places-autocomplete: ^4.0.1 => 4.0.1 util: ^0.12.5 => 0.12.5 uuid: ^9.0.1 => 9.0.1 (8.0.0, 3.4.0, 3.1.0) vite: ^4.4.11 => 4.5.3 vite-jsconfig-paths: ^2.0.1 => 2.0.1 web-vitals: ^3.4.0 => 3.5.2 web-worker: ^1.3.0 => 1.3.0 yup: ^1.2.0 => 1.4.0 npmGlobalPackages: gltf-pipeline: 4.1.0 yarn: 1.22.22 ```

Describe the bug

Im unable to create the session cookies for the Social Login.

Funny thing is that the session is workin with email and password but not when social login is made. In Localhost enviroment the cookies work tought.

Expected behavior

The cookie behaivor needs to be created for domain like a usual login request.

Reproduction steps

  1. Install Amplify
  2. Configure amplify
  3. Add redirect urls and providers
  4. Try session cookies on live domain

Code Snippet

const isLocalhost = window.location.hostname === "localhost";

export const cookieConfiguration = { 
    domain: isLocalhost ? 'localhost' : 'test.com',
    secure: !isLocalhost, // Use true for HTTPS, false for HTTP
    sameSite: isLocalhost ? 'lax' : 'none',
};
import { RouterProvider } from 'react-router-dom';

// project import
import router from 'routes';
import ThemeCustomization from 'themes';

import Locales from 'components/Locales';
import RTLLayout from 'components/RTLLayout';
import ScrollTop from 'components/ScrollTop';
import Snackbar from 'components/@extended/Snackbar';
import Notistack from 'components/third-party/Notistack';

// auth provider
// import { JWTProvider as AuthProvider } from 'contexts/JWTContext';
// import { FirebaseProvider as AuthProvider } from 'contexts/FirebaseContext';
import { AWSCognitoProvider as AuthProvider } from 'contexts/AWSCognitoContext';
// import { Auth0Provider as AuthProvider } from 'contexts/Auth0Context';
import { Amplify } from 'aws-amplify';
import { awsconfig } from 'aws-exports';
Amplify.configure(awsconfig);
import { CookieStorage } from 'aws-amplify/utils';
import { cognitoUserPoolsTokenProvider } from '@aws-amplify/auth/cognito';
import { cookieConfiguration } from 'cookies';
cognitoUserPoolsTokenProvider.setKeyValueStorage(new CookieStorage(cookieConfiguration));

// ==============================|| APP - THEME, ROUTER, LOCAL ||============================== //
import 'react-loading-skeleton/dist/skeleton.css';

const App = () => {
  return (
    <ThemeCustomization>
      <RTLLayout>
        <Locales>
          <ScrollTop>
            <AuthProvider>
              <>
                <Notistack>
                  <RouterProvider router={router} />
                  <Snackbar />
                </Notistack>
              </>
            </AuthProvider>
          </ScrollTop>
        </Locales>
      </RTLLayout>
    </ThemeCustomization>
  );
};

export default App;

My Component for the code response:


import { useEffect, useState } from 'react';
import { Hub } from 'aws-amplify/utils';
import { Amplify } from 'aws-amplify';
import { useLocation, useNavigate } from 'react-router-dom';
import { getCurrentUser } from 'aws-amplify/auth';
import { fetchAuthSession } from 'aws-amplify/auth';

const SocialContext = () => {
  const navigate = useNavigate();
  const location = useLocation();

  useEffect(() => {
    const handleOAuthResponse = async () => {
      try {
        // Completing the OAuth flow manually
        const { username, userId, signInDetails } = await getCurrentUser();
        if(username){
            await fetchAuthSession({ forceRefresh: true });
            navigate('/dashboards/analytics', {
                state: { from: location.pathname }
            });
        }else{
          navigate('/login', {
            state: { from: location.pathname }
        });
        }
      } catch (error) {
        console.error('OAuth flow failed', error.message);
        navigate('/login', {
            state: { from: location.pathname }
        });
      }
    };
    handleOAuthResponse();
  }, []);
};

export default SocialContext;

It only seems to work with the same Cognito App Integration with redirect url for localhost but not for a live domain.

https://mydomain.com/auth/session/external/signin?code=zzzzz-9ca9-4f0a-b016-319f270ec78c&state=zzzzzzz

This example of the response code do nothing on live domain with the component so ,getCurrentUser doesnt bring any data and no cookies are created.

Log output

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

aws-exports.js

export const awsconfig = {
    aws_project_region: 'us-east-1',
    aws_cognito_identity_pool_id: 'us-east-1:xxxx-xxx-xxx-xx-xx',
    aws_cognito_region: 'us-east-1',
    aws_user_pools_id: 'us-east-xxx',
    aws_user_pools_web_client_id: 'xxxxxx',
    oauth: {
        domain: 'custom-domain.auth.us-east-1.amazoncognito.com',
        scope: ['email', 'openid', 'profile', 'aws.cognito.signin.user.admin'],
        redirectSignIn: 'https://mydomain/auth/session/external/signin',
        redirectSignOut: 'https://mydomain/auth/session/external/logout',
        responseType: 'code',
        options: {
            prompt: 'select_account' // Force account selection
        },
    }
};

Manual configuration

export const awsconfig = {
    aws_project_region: 'us-east-1',
    aws_cognito_identity_pool_id: 'us-east-1:xxxx-xxx-xxx-xx-xx',
    aws_cognito_region: 'us-east-1',
    aws_user_pools_id: 'us-east-xxx',
    aws_user_pools_web_client_id: 'xxxxxx',
    oauth: {
        domain: 'custom-domain.auth.us-east-1.amazoncognito.com',
        scope: ['email', 'openid', 'profile', 'aws.cognito.signin.user.admin'],
        redirectSignIn: 'https://mydomain/auth/session/external/signin',
        redirectSignOut: 'https://mydomain/auth/session/external/logout',
        responseType: 'code',
        options: {
            prompt: 'select_account' // Force account selection
        },
    }
};

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

HuiSF commented 4 months ago

Hi @ulisescarreonalvarez

Firstly, looking at your code examples, when isLocalhost === false, you are setting cookie domain as shedcloudtest.com, is this the domain that your web app is hosted on?

Secondly, you are in your cookieConfiguration you have not specified path. Amplify requires setting auth token in cookie store with path: '/' so it can retrieve the auth token when needed. If you are not setting path to the root, by default your auth token may be set to the path component in the current url. e.g. /auth/session/external, which makes the auth token cookies only be accessible when the url matches the path.

Can you confirm the above items and try again?

ulisescarreonalvarez commented 4 months ago

I added the path before:

export const cookieConfiguration = { 
    secure: !isLocalhost,
    sameSite: isLocalhost ? 'lax' : 'none',
    path: "/"
};

But the cookies doesnt create at all when is Social Login, the code is received on my path but the is stuck loading, no error whatsover but is because no cookies are created automatically, i tried to add path, and add the domain direclty, trying to use lax, none, etc but the issue is persisting on Social Login.

HuiSF commented 4 months ago

Thanks for the follow up @ulisescarreonalvarez

But the cookies doesn't create at all when is Social Login

Do you call the signInWithRedirect() API to initiate the social sign in flow (this is required)?

If "yes", is mydomain.com/auth/session/external/signin where you called the signInWithRedirect() API from? If "no" please take a look at this documentation.

Also could you confirm was there a fetch call made to custom-domain.auth.us-east-1.amazoncognito.com/oauth2/token for exchanging tokens after redirecting back to mydomain/auth/session/external/signin?

ulisescarreonalvarez commented 4 months ago

So, im calling signInWithRedirect on my login page, the auth/session/external/signin is a redirect path that i had before on the application user pool, i never exchange code for tokens, the cookies usually are created automatically on the App, the issue is new for use with the new gen of amplify, we neved had an issue with the cookies until Gen 2 on our new project using an existing application :

const AuthLogin = () => {

 const navigation = useNavigate();
  const [checked, setChecked] = React.useState(false);
  const [verification, setVerification] = React.useState(false);
  const { login } = useAuth();
  const scriptedRef = useScriptRef();
  const [showPassword, setShowPassword] = React.useState(false);
  const handleClickShowPassword = () => {
    setShowPassword(!showPassword);
  };

  const handleMouseDownPassword = (event) => {
    event.preventDefault();
  };

  const signInWithGoogle = () => {
    signInWithRedirect({ provider: "Google" })
  };

called on a button.

  <Grid item xs={12}>
                  <AnimateButton>
                    <Button
                      id="googleSignInButton" // Add this id to the button element
                      disableElevation
                      fullWidth
                      size="large"
                      type="button"
                      variant="dashed"
                      color="error"
                      startIcon={<GoogleOutlined/>}
                      onClick={signInWithGoogle}

                    >
                      <FormattedMessage id="google-login" />
                    </Button>
                  </AnimateButton>
                </Grid>
HuiSF commented 4 months ago

So, im calling signInWithRedirect on my login page, the auth/session/external/signin is a redirect path that i had before on the application user pool

Is your login page and auth/session/external/signin under the same domain? Is your app a single page application and is auth/session/external/signin a route of the SPA app?

the issue is new for use with the new gen of amplify, we neved had an issue with the cookies until Gen 2 on our new project using an existing application :

To clarify, your existing application uses also Amplify v6, and it works with your Gen1 backend resource? Amplify JS v6 remained the same between Gen1 and Gen2, there is no difference on the library side.

Also could you confirm was there a fetch call made to custom-domain.auth.us-east-1.amazoncognito.com/oauth2/token for exchanging tokens after redirecting back to mydomain/auth/session/external/signin?

Can you watch this in the network tab in developer tool? This is handled by the library, if you don't see this happening while redirecting back to auth/session/external/signin that means something disturbs the social sign in flow, and we need to identity the root cause.

ulisescarreonalvarez commented 4 months ago

Ok, so is a multi-page, we are using routing for the application (react-router-dom).

Yes, the path is in the same project.

Backend is the same for the project, we have another project (old amplify version) that works fine with the cookies.

The network, works fine, it returns the code and the state but is stuck on the cookie creation because the getCurrentUser wont call it, like the useEffect not working because the library seems to not to finish the procces.

HuiSF commented 4 months ago

If it's a multipage application, and the route auth/session/external/signin doesn't bundle signInWithRedirect() API call, you would need to follow this documentation to do one extra setup.

ulisescarreonalvarez commented 4 months ago

That seems to make it work, thanks!