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

cookieStorage does not work #9176

Closed serjiosilent closed 3 years ago

serjiosilent commented 3 years ago

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

Authentication

Amplify Categories

auth, api

Environment information

``` System: OS: macOS 12.0.1 Shell: 5.8 - /bin/zsh Binaries: Node: 17.0.1 - /usr/local/bin/node npm: 8.1.0 - /usr/local/bin/npm Watchman: 2021.10.18.00 - /usr/local/bin/watchman Browsers: Chrome: 95.0.4638.69 Safari: 15.1 npmPackages: @aws-sdk/client-iot: ^3.39.0 => 3.39.0 @babel/cli: ^7.16.0 => 7.16.0 @babel/core: ^7.16.0 => 7.16.0 @babel/eslint-parser: ^7.16.0 => 7.16.0 @babel/plugin-proposal-class-properties: ^7.16.0 => 7.16.0 @babel/preset-env: ^7.16.0 => 7.16.0 @babel/preset-react: ^7.16.0 => 7.16.0 @date-io/date-fns: ^1.3.13 => 1.3.13 @material-ui/core: ^4.12.3 => 4.12.3 @material-ui/icons: ^4.11.2 => 4.11.2 @material-ui/lab: ^4.0.0-alpha.60 => 4.0.0-alpha.60 @material-ui/pickers: ^3.3.10 => 3.3.10 @reduxjs/toolkit: ^1.6.2 => 1.6.2 @reduxjs/toolkit-query: 1.0.0 @reduxjs/toolkit-query-react: 1.0.0 @sentry/react: ^6.14.1 => 6.14.1 @sentry/tracing: ^6.14.1 => 6.14.1 @slack/web-api: ^6.4.0 => 6.4.0 @svgr/webpack: ^5.5.0 => 5.5.0 amazon-cognito-identity-js: ^5.2.2 => 5.2.2 autosuggest-highlight: ^3.2.0 => 3.2.0 aws-amplify: ^4.3.4 => 4.3.4 axios: ^0.24.0 => 0.24.0 (0.21.4) babel-loader: ^8.2.3 => 8.2.3 branch-sdk: ^2.59.0 => 2.59.0 clean-webpack-plugin: ^4.0.0 => 4.0.0 clsx: ^1.1.1 => 1.1.1 copy-webpack-plugin: ^9.0.1 => 9.0.1 core-js: ^3.19.1 => 3.19.1 (3.6.5) crypto-browserify: ^3.12.0 => 3.12.0 css-loader: ^6.5.1 => 6.5.1 date-fns: ^2.25.0 => 2.25.0 date-fns-tz: ^1.1.6 => 1.1.6 dotenv-webpack: ^7.0.3 => 7.0.3 eslint: ^8.1.0 => 8.1.0 eslint-config-prettier: ^8.3.0 => 8.3.0 eslint-config-react-app: ^6.0.0 => 6.0.0 eslint-plugin-flowtype: ^8.0.3 => 8.0.3 eslint-plugin-import: ^2.25.2 => 2.25.2 eslint-plugin-jsx-a11y: ^6.4.1 => 6.4.1 eslint-plugin-prettier: ^4.0.0 => 4.0.0 eslint-plugin-react: ^7.26.1 => 7.26.1 eslint-plugin-react-hooks: ^4.2.0 => 4.2.0 file-loader: ^6.2.0 => 6.2.0 firebase: ^9.3.0 => 9.3.0 firebase/analytics: undefined () firebase/app: undefined () firebase/app-check: undefined () firebase/auth: undefined () firebase/auth/cordova: undefined () firebase/auth/react-native: 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/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/messaging: undefined () firebase/messaging/sw: undefined () firebase/performance: undefined () firebase/remote-config: undefined () firebase/storage: undefined () generate-password: ^1.6.1 => 1.6.1 history: ^4.10.1 => 4.10.1 html-webpack-plugin: ^5.5.0 => 5.5.0 husky: ^7.0.4 => 7.0.4 jwt-decode: ^3.1.2 => 3.1.2 lint-staged: ^11.2.6 => 11.2.6 lodash: ^4.17.21 => 4.17.21 material-ui-phone-number: ^2.2.6 => 2.2.6 moment: ^2.29.1 => 2.29.1 node-sass: ^6.0.1 => 6.0.1 notistack: ^1.0.10 => 1.0.10 password-generator: ^2.3.2 => 2.3.2 prettier: ^2.4.1 => 2.4.1 process: ^0.11.10 => 0.11.10 prop-types: ^15.7.2 => 15.7.2 react: ^17.0.2 => 17.0.2 (16.14.0) react-copy-to-clipboard: ^5.0.4 => 5.0.4 react-countdown: ^2.3.2 => 2.3.2 react-cropper: ^2.1.8 => 2.1.8 react-dom: ^17.0.2 => 17.0.2 (16.14.0) react-dropzone: ^11.4.2 => 11.4.2 react-helmet: ^6.1.0 => 6.1.0 react-html5-camera-photo: ^1.5.5 => 1.5.5 react-infinite-scroll-component: ^6.1.0 => 6.1.0 react-quill: ^2.0.0-beta.2 => 2.0.0-beta.4 react-redux: ^7.2.6 => 7.2.6 react-router: ^5.2.1 => 5.2.1 react-router-dom: ^5.3.0 => 5.3.0 react-youtube: ^7.13.1 => 7.13.1 redux: ^4.1.2 => 4.1.2 redux-devtools-extension: ^2.13.9 => 2.13.9 redux-logger: ^3.0.6 => 3.0.6 redux-saga: ^1.1.3 => 1.1.3 redux-saga/effects: undefined () redux-sentry-middleware: ^0.2.2 => 0.2.2 regenerator-runtime: ^0.13.9 => 0.13.9 sass-loader: ^12.3.0 => 12.3.0 stream-browserify: ^3.0.0 => 3.0.0 style-loader: ^3.3.1 => 3.3.1 typeface-roboto: 1.1.13 => 1.1.13 url-loader: ^4.1.1 => 4.1.1 userpilot: ^1.2.5 => 1.2.5 util: ^0.12.4 => 0.12.4 uuid: ^8.3.2 => 8.3.2 (3.4.0) validator: ^13.7.0 => 13.7.0 webpack: ^5.61.0 => 5.61.0 webpack-cli: ^4.9.1 => 4.9.1 webpack-dev-server: ^4.4.0 => 4.4.0 npmGlobalPackages: @aws-amplify/cli: 4.11.0 create-react-app: 4.0.0 editorconfig: 0.15.3 eslint: 6.8.0 expo-cli: 3.28.2 expo: 39.0.3 npm-check-updates: 12.0.0 npm: 8.1.0 prettier: 2.3.1 react-app-rewired: 2.1.6 react-native-cli: 2.0.1 webpack-cli: 3.3.10 ```

Describe the bug

Configured Amplify for using cookieStorage instead localStorage. When I'm trying to login, have an error: "AuthClass - Failed to get the signed in user No current user" Also, user tokens saving to local storage, not to cookies

Expected behavior

Setting up user tokens to cookies and logged in user

Reproduction steps

  1. Installed AWS Amplify
  2. Configured Amplify config by official docs with cookieStorage
  3. Trying to login
  4. See error "AuthClass - Failed to get the signed in user No current user"

Code Snippet

function* getUserData() {
  const user = yield call([Auth, 'currentAuthenticatedUser']);
  const userFromApi = yield call([API, 'getUserFromApi']);
  const info = { username: user.username, ...userFromApi.data };

  return info;
}

function* signIn(username) {
  try {
    const signedInUser = yield call([Auth, 'signIn'], username);
    yield put(signInSuccess({ ...signedInUser }));
  } catch (e) {
    yield put(signInError(e));
  }
}

function* signInSaga(action) {
  const { username } = action.payload;

  try {
    const password = generate({ length: 16, numbers: true });
    const params = {
      password,
      username,
      attributes: {
        email: `${username}@example.com`,
      },
    };

    yield call([Auth, 'signUp'], { ...params });
    yield call(signIn, username);
  } catch (e) {
    if (e.code === 'UsernameExistsException') {
      yield call(signIn, username);
    } else {
      yield put(signInError(e));
    }
  }
}

function* logInSaga(action) {
  try {
    const { user, code } = action.payload;
    const cognitoUser = new CognitoUser({
      Username: user.username,
      Pool: new CognitoUserPool({
        UserPoolId: AWS_USER_POOL_ID,
        ClientId: AWS_CLIENT_ID,
      }),
    });
    cognitoUser.Session = user.Session;
    cognitoUser.setAuthenticationFlowType(AWS_AUTH_FLOW_TYPE);

    yield call([Auth, 'sendCustomChallengeAnswer'], cognitoUser, code);

    const userData = yield getUserData();
    yield put(logInSuccess(userData));
  } catch (e) {
    yield put(logInError(e));
  }
}

Log output

``` [ERROR] 22:58.74 AuthClass - Failed to get the signed in user No current user ```

aws-exports.js

No response

Manual configuration

{
    Auth: {
      identityPoolId: AWS_IDENTITY_POOL_ID,
      region: AWS_REGION,
      userPoolId: AWS_USER_POOL_ID,
      userPoolWebClientId: AWS_CLIENT_ID,
      authenticationFlowType: AWS_AUTH_FLOW_TYPE, //CUSTOM_AUTH

      cookieStorage: {
        domain: AMPLIFY_COOKIE_DOMAIN, //localhost or .<domain>.com
        path: '/',
        expires: 365,
        sameSite: 'strict',
        secure: AMPLIFY_COOKIE_DOMAIN !== 'localhost', 
      },
    },
  }

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

serjiosilent commented 3 years ago

Any thoughts?

chrisbonifacio commented 3 years ago

Hi @serjiosilent 👋 I'm curious why you're using aws-cognito-identity-js separately if it is already a dependency of aws-amplify? I configured cookieStorage similar to you in my project and did not run into this issue. I used the AmplifyAuthenticator ui component to sign in but this should work the same way if you use the Auth.signIn method directly.

// index.js
import { Amplify } from "aws-amplify";
import config from "./aws-exports";
Amplify.configure({
  ...config,
  Auth: {
    ...config,
    cookieStorage: {
      domain: "localhost",
      path: "/",
      expires: 365,
      sameSite: "strict",
      secure: process.env.REACT_APP_AMPLIFY_COOKIE_DOMAIN !== "localhost",
    },
  },
});

localStorage

Screen Shot 2021-11-11 at 10 54 10 AM

cookies

Screen Shot 2021-11-11 at 10 54 27 AM
serjiosilent commented 3 years ago

Hi @chrisbonifacio! Thanks for respond. I'm using CUSTOM_AUTH flow type for password less authentication and I had an error relates on sendCustomChallengeAnswer method - user.sendCustomChallengeAnswer is not a function. And using CognitoUser instance from aws-cognito-identity-js resolved this issue

serjiosilent commented 3 years ago

@chrisbonifacio I found a bug. I saved user object from response to redux-store and after that put it to sign in, but this user does not have sendCustomChallengeAnswer method. So, right now I'm saving user object on a temp variable on the code and it works without CognitoUser instance. Also, removing CognitoUser fixed issue with cookieStorage. Thanks for point to right direction

chrisbonifacio commented 3 years ago

oh 😮 I was going to point out this code snippet from the docs on using Auth library with a custom auth flow https://docs.amplify.aws/lib/auth/switch-auth/q/platform/js/#custom-authentication-flow

import { Auth } from 'aws-amplify';

Auth.configure({
    // other configurations
    // ...
    authenticationFlowType: 'CUSTOM_AUTH'
});

let challengeResponse = "the answer for the challenge";

Auth.signIn(username, password)
    .then(user => {
        if (user.challengeName === 'CUSTOM_CHALLENGE') {
            // to send the answer of the custom challenge
            Auth.sendCustomChallengeAnswer(user, challengeResponse)
                .then(user => console.log(user))
                .catch(err => console.log(err));
        } else {
            console.log(user);
        }
    })
    .catch(err => console.log(err));

You can use the sendCustomChallengeAnswer from the Auth library and pass in the user returned from Auth.signIn.

ColmBhandal commented 2 years ago

Also, user tokens saving to local storage, not to cookies

I thought so too, but in my case it was because I still had old tokens from previous testing I was doing without cookieStorage set. Posting this for future readers in case this is your issue. Best way to check is to clear the local storage and try again.

I've tested this a few times and it seems the tokens are always saving to the Cookies storage whenever cookieStorage is in place, and are saving to local storage otherwise (e.g. when I comment out cookieStorage).

Loosely related but diverging a bit, it's good to know the pros/cons of cookie vs. local storage.

github-actions[bot] commented 1 year ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server amplify-help forum.