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.43k stars 2.12k forks source link

Authentication does not work with CUSTOM_AUTH and with CONTINUE_SIGN_IN_WITH_MFA_SELECTION #13123

Open celica-vladimir opened 7 months ago

celica-vladimir commented 7 months ago

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

Authentication

Amplify Version

v6

Amplify Categories

auth

Backend

None

Environment information

``` # Put output below this line Invalid session for the user, session can only be used once. ```

Describe the bug

We have a custom authentication flow with cognito triggers/lambdas. We created a user and enabled both MFA's, SMS and TOTP. We don't set preffered MFA because we want to allow user to choose appropriate MFA. When users select SMS MFA user get's error "Invalid session for the user, session can only be used once."

Expected behavior

In case of USER_SRP_AUTH, login works with user who have SMS and TOTP MFA enabled. When switch to CUSTOM_WITH_SRP, only TOTP works, but not SMS MFA.

Reproduction steps

  1. create cognito with optional mfa
  2. create a user with both MFA's, SMS and TOTP
  3. don't prefer any MFA, allow user to choose
  4. create a simple custom flow
  5. switch to CUSTOM_WITH_SRP
  6. try to login with SMS MFA

Code Snippet

// Put your code below this line.

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

celica-vladimir commented 7 months ago

@cwomack just to share that I think that this is a issue on Cognito API, because in failed request to cognito contains appropriate. Do you have a way to check with someone on Cognito API side?

cwomack commented 7 months ago

Hello, @celica-vladimir 👋 and apologies on the delay in response here! Just to confirm, is this with a Gen1 (CLI generated backend) app or is this on a Gen2 (currently in Developer Preview)? Also, if you could share any relevant frontend code that's making the Auth API calls as well as your package.json, that would be extremely helpful!

As for what's not working, is it that you get the Invalid session for the user, session can only be used once. error when you're attempting to sign in?

celica-vladimir commented 7 months ago

Hey @cwomack, we did not generated backend via CLI. We are using Amplify Auth component only for authorization with Cognito.

Package file: package.json

Amplify config:

import { Amplify } from 'aws-amplify';

Amplify.configure({
  Auth: {
    Cognito: {
      // OPTIONAL - Amazon Cognito User Pool ID
      userPoolId: process.env.REACT_APP_COGNITO_USER_POOL_ID,

      // OPTIONAL - Amazon Cognito Web Client ID (26-char alphanumeric string)
      userPoolClientId: process.env.REACT_APP_COGNITO_WEB_CLIENT_ID,

      // REQUIRED only for Federated Authentication - Amazon Cognito Identity Pool ID
      identityPoolId: process.env.REACT_APP_COGNITO_IDENTITY_POOL_ID,

      authenticationFlowType: "CUSTOM_AUTH",

      loginWith: {
        // OPTIONAL - Hosted UI configuration
        oauth: {
          domain: process.env.REACT_APP_OAUTH_DOMAIN,
          scopes: ['openid'],
          redirectSignIn: [process.env.REACT_APP_OAUTH_CALLBACK_URL],
          redirectSignOut: [process.env.REACT_APP_OAUTH_CALLBACK_URL],
          responseType: 'code',
        },
      },
    },
  },
});

export default Amplify.getConfig();

Code signIn:

async handleSignIn(formData) {
    const payload = {
      ...formData,
      options: {
        authFlowType: 'CUSTOM_WITH_SRP',
      },
    };
    const user = await signIn(payload);

    console.log('user?.nextStep', 'user?.nextStep');

    if (
      user?.nextStep?.signInStep === 'CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE'
    ) {
      if (user?.nextStep?.additionalInfo.siteKey) {
        updateSiteKey(user.nextStep.additionalInfo.siteKey);
      }
    } else if (
      user?.nextStep?.signInStep === 'CONTINUE_SIGN_IN_WITH_MFA_SELECTION'
    ) {
      try {
        return await handleMFASelect(user);
      } catch (error) {
        window.location.reload();
      }
    }
    return user;
  }

Code handleMFASelect:

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

import MFASelectModal from './MFASelectModal';

const handleMFASelect = async ({ nextStep }) => {
  const mfaType = await MFASelectModal({
    allowedMFATypes: nextStep.allowedMFATypes,
  });

  return confirmSignIn({
    challengeResponse: mfaType,
  });
};

export default handleMFASelect;
celica-vladimir commented 7 months ago

@cwomack Regarding 'Invalid session for the user, session can only be used once' it happens when user's enter SMS MFA code (please note that user SMS MFA and TOTP MFA and none is preferred on cognito side). What is weird is that login works in case if TOTP MFA is chosed. When error happen, we compared Session value from previous request's response and from error request payload and they are the same. Another weird thing is that if user have only one MFA device assigned, both SMS and TOTP are working. Also, if user have only SMS MFA and there is no preferred MFA, it is working.

In past everything worked fine until we switched from SRP_A to CUSTOM_FLOW.

cwomack commented 7 months ago

@celica-vladimir when you state that your users have more than one device assigned, can you confirm if you have device tracking enabled for this user pool?

celica-vladimir commented 7 months ago

@cwomack It is not, option "Don’t remember" is selected.

haverchuck commented 4 months ago

Marking as feature request.