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

amazon-cognito-identity-js: sendMFACode not working for SMS_MFA #9734

Closed CameronGuitard closed 2 years ago

CameronGuitard commented 2 years ago

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

Authentication

Amplify Categories

auth

Environment information

``` # Put output below this line System: OS: Windows 10 10.0.19043 CPU: (8) x64 Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz Memory: 3.95 GB / 15.94 GB Binaries: Node: 14.18.2 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.17 - C:\Program Files\nodejs\yarn.CMD npm: 6.14.15 - C:\Program Files\nodejs\npm.CMD Browsers: Chrome: 99.0.4844.82 Edge: Spartan (44.19041.1266.0), Chromium (99.0.1150.46) Internet Explorer: 11.0.19041.1566 npmPackages: @ampproject/toolbox-optimizer: undefined () @aws-sdk/client-cognito-identity-provider: ^3.16.0 => 3.51.0 @aws-sdk/types: ^3.15.0 => 3.50.0 @babel/core: undefined () @babel/runtime: 7.15.4 @emotion/react: ^11.1.5 => 11.7.1 @emotion/styled: ^11.3.0 => 11.6.0 @hapi/accept: undefined () @innovasium-2014/mui-datatables: ^2.0.0 => 2.0.0 @marker.io/browser: ^0.10.0 => 0.10.0 @mui/icons-material: ^5.1.0 => 5.4.2 @mui/lab: ^5.0.0-alpha.54 => 5.0.0-alpha.69 @mui/material: ^5.1.0 => 5.4.2 @mui/styles: ^5.1.0 => 5.4.2 @napi-rs/triples: undefined () @next/bundle-analyzer: ^12.1.0 => 12.1.0 @next/react-dev-overlay: undefined () @next/react-refresh-utils: 12.1.0 @peculiar/webcrypto: undefined () @prisma/client: ^3.4.0 => 3.9.2 @sendgrid/mail: ^7.6.2 => 7.6.2 @sentry/cli: ^1.67.1 => 1.72.2 @sentry/nextjs: ^6.11.0 => 6.17.9 @stripe/react-stripe-js: ^1.6.0 => 1.7.0 @stripe/stripe-js: ^1.21.1 => 1.23.0 @trivago/prettier-plugin-sort-imports: ^3.2.0 => 3.2.0 @types/cookie: ^0.4.0 => 0.4.1 @types/faker: ^5.5.7 => 5.5.9 @types/jest: ^27.0.2 => 27.4.0 @types/jsonwebtoken: ^8.5.1 => 8.5.8 @types/jwk-to-pem: ^2.0.0 => 2.0.1 @types/node: ^16.11.11 => 16.11.25 (17.0.18) @types/pg: ^8.6.1 => 8.6.4 @types/pizzip: ^3.0.2 => 3.0.2 @types/react: ^17.0.3 => 17.0.39 @types/react-beautiful-dnd: ^13.1.2 => 13.1.2 @types/react-html-parser: ^2.0.2 => 2.0.2 @types/react-window: ^1.8.3 => 1.8.5 @types/stripe: ^8.0.417 => 8.0.417 @types/uuid: ^8.3.1 => 8.3.4 @types/yup: ^0.29.11 => 0.29.13 @typescript-eslint/eslint-plugin: ^5.12.0 => 5.12.0 @typescript-eslint/parser: ^5.12.0 => 5.12.0 @vercel/nft: undefined () abort-controller: undefined () acorn: undefined () amazon-cognito-identity-js: ^5.2.8 => 5.2.8 amphtml-validator: undefined () apexcharts: ^3.26.2 => 3.33.1 arg: undefined () assert: undefined () async-retry: undefined () async-sema: undefined () aws-sdk: ^2.946.0 => 2.1075.0 axios: ^0.26.0 => 0.26.0 axios-mock-adapter: ^1.20.0 => 1.20.0 babel-packages: undefined () browserify-zlib: undefined () browserslist: undefined () buffer: undefined () chalk: undefined () ci-info: undefined () cli-select: undefined () comment-json: undefined () compression: undefined () conf: undefined () constants-browserify: undefined () content-disposition: undefined () content-type: undefined () cookie: ^0.4.1 => undefined (0.4.2, ) cross-env: ^7.0.3 => 7.0.3 cross-spawn: undefined () crossfilter2: ^1.5.4 => 1.5.4 crypto-browserify: undefined () cssnano-simple: undefined () date-fns: ^2.20.0 => 2.28.0 debug: undefined () devalue: undefined () docxtemplater: ^3.28.2 => 3.29.0 docxtemplater-image-module-free: ^1.1.1 => 1.1.1 domain-browser: undefined () dotenv: ^16.0.0 => 16.0.0 eslint: ^8.9.0 => 8.9.0 eslint-config-next: ^12.1.0 => 12.1.0 eslint-config-prettier: ^8.3.0 => 8.3.0 eslint-plugin-jest: ^26.1.1 => 26.1.1 etag: undefined () events: undefined () faker: ^5.5.3 => 5.5.3 find-cache-dir: undefined () find-up: undefined () formdata-node: undefined () formik: ^2.2.6 => 2.2.9 fresh: undefined () get-orientation: undefined () glob: undefined () gzip-size: undefined () http-proxy: undefined () https-browserify: undefined () i18next: ^21.6.11 => 21.6.11 icss-utils: undefined () ignore-loader: undefined () image-size: undefined () is-animated: undefined () is-docker: undefined () is-wsl: undefined () jest: ^27.2.4 => 27.5.1 jest-worker: undefined () json5: undefined () jsonwebtoken: ^8.5.1 => undefined (8.5.1, ) jwk-to-pem: ^2.0.5 => 2.0.5 loader-utils: undefined () lodash: ^4.17.21 => 4.17.21 lodash.curry: undefined () lru-cache: undefined () marker-io-sdk-example-vanilla: 0.1.0 marker-io-sdk-example-vue: 0.1.0 micromatch: undefined () mini-css-extract-plugin: undefined () nanoid: undefined () native-url: undefined () neo-async: undefined () next: ^12.1.0 => 12.1.0 node-fetch: undefined () node-html-parser: undefined () notistack: ^2.0.3 => 2.0.3 ora: undefined () os-browserify: undefined () p-limit: undefined () path-browserify: undefined () pg: ^8.7.1 => 8.7.3 pizzip: ^3.1.1 => 3.1.1 postcss-flexbugs-fixes: undefined () postcss-modules-extract-imports: undefined () postcss-modules-local-by-default: undefined () postcss-modules-scope: undefined () postcss-modules-values: undefined () postcss-preset-env: undefined () postcss-safe-parser: undefined () postcss-scss: undefined () postcss-value-parser: undefined () prettier: ^2.3.2 => 2.5.1 prisma: ^3.5.0 => 3.9.2 process: undefined () punycode: undefined () querystring-es3: undefined () raw-body: ^2.4.1 => 2.4.3 () react: 17.0.2 => 17.0.2 (16.14.0) react-apexcharts: ^1.3.9 => 1.3.9 react-beautiful-dnd: ^13.1.0 => 13.1.0 react-dom: 17.0.2 => 17.0.2 (16.14.0) react-dropzone: ^11.3.2 => 11.7.1 react-html-parser: ^2.0.2 => 2.0.2 react-html-parser-demo: 0.0.0 react-i18next: ^11.8.15 => 11.15.4 react-is: 17.0.2 react-perfect-scrollbar: ^1.5.8 => 1.5.8 react-qr-code: ^2.0.3 => 2.0.3 react-quill: ^1.3.5 => 1.3.5 react-refresh: 0.8.3 react-server-dom-webpack: undefined () reflect-metadata: ^0.1.13 => 0.1.13 regenerator-runtime: 0.13.4 sass-loader: undefined () schema-utils: undefined () semver: undefined () send: undefined () setimmediate: undefined () source-map: undefined () stream-browserify: undefined () stream-http: undefined () string-hash: undefined () string_decoder: undefined () strip-ansi: undefined () stripe: ^8.191.0 => 8.203.0 swr: ^1.2.1 => 1.2.1 swr-immutable: 0.0.1 swr-infinite: 0.0.1 terser: undefined () text-table: undefined () tf-next: ^0.10.2 => 0.10.2 timers-browserify: undefined () ts-jest: ^27.0.5 => 27.1.3 ts-node: ^10.0.0 => 10.5.0 tsyringe: ^4.6.0 => 4.6.0 tty-browserify: undefined () typescript: ^4.2.3 => 4.5.5 ua-parser-js: undefined () unistore: undefined () util: undefined () uuid: ^8.3.2 => 8.3.2 (3.3.2, ) vm-browserify: undefined () watchpack: undefined () web-streams-polyfill: undefined () web-vitals: undefined () webpack: undefined () webpack-sources: undefined () with-typescript: undefined () ws: undefined () yup: ^0.32.11 => 0.32.11 npmGlobalPackages: npm: 6.14.15 yarn: 1.22.17 ```

Describe the bug

The sendMFACode function with the "SMS_MFA" mfaType is failing with a codeMissmatch exception and a new code is sent to their phone. The users phone number is verified and the accounts have SMS_MFA enabled. I have triple checked that the code getting sent with the sendMFACode function matches the one received in the text. This same workflow works for the "SOFTWARE_TOKEN_MFA"mfaType.

This is using the amazon-cognito-identity-js package

Expected behavior

When the user enters the code sent to their phone, the sendMFACode calls the "onSuccess" callback

Reproduction steps

Add a phone number to a user that is logged in Verify phone number and enable SMS_MFA to account Signout Attempt to login mfaRequired callback is hit, code is sent to use, and app allows user to enter phone code user enters the code that was sent to them sendMFACode fails with CodeMismatchException

Code Snippet

// Put your code below this line.
 user.authenticateUser(
        new AuthenticationDetails({
          Username: //Users username,
          Password: //Users password,
        }),
        {
          onFailure: (err: Error) => {

          },
          newPasswordRequired: () => {
            resolve({
              valid: true,
              status: "FORCE_CHANGE_PASSWORD",
            });
          },
          onSuccess: (ctx) => {
           //handle login
          },
          totpRequired: () => {

            if (params.mfaCode) {
              user.sendMFACode(
                params.mfaCode,
                {
                  onFailure: (err: Error) => {
                    reject(new BadRequestException(err.message));
                  },
                  onSuccess: (ctx) => {
                    //Handle valid user
                  },
                },
                "SOFTWARE_TOKEN_MFA"
              );
            } else {
              resolve({
                valid: true,
                status: "NEED_MFA",
              });
            }
          },
          mfaRequired: () => {
            if (params.mfaCode) {
              user.sendMFACode(
                params.mfaCode,
                {
                  onFailure: (err: Error) => {
                    reject(new BadRequestException(err.message));
                  },
                  onSuccess: (ctx) => {
                    //HandleValid user
                  },
                },
                "SMS_MFA"
              );
            } else {
              resolve({
                valid: true,
                status: "NEED_MFA",
              });
            }
          },
        }
      );

Log output

CodeMismatchException: Invalid code or auth state for the user. at REDACTED\amazon-cognito-identity-js\lib\Client.js:153:19 at runMicrotasks () at processTicksAndRejections (internal/process/task_queues.js:95:5) { code: 'CodeMismatchException' }

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

CameronGuitard commented 2 years ago

I have discovered that the issue lies within my login workflow. Since to attempt to verify the code after the initial MFA required callback, the same login workflow was called including the authenticateUser call which sends a new code to the users phone, making the code they entered properly incorrect. The TOTP workflow still worked since the timer/code is independent from the authenticateUser call.

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 *-help channels or Discussions for those types of questions.