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

Error in initiating SOFTWARE_TOKEN_MFA flow after Passwordless CUSTOM_CHALLENGE flow. #12887

Open campbellborder opened 6 months ago

campbellborder commented 6 months ago

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

Not applicable

Amplify Version

v6

Amplify Categories

auth

Backend

Other

Environment information

``` # Put output below this line System: OS: Windows 10 10.0.19045 CPU: (12) x64 AMD Ryzen 5 3600XT 6-Core Processor Memory: 6.79 GB / 15.95 GB Binaries: Node: 21.5.0 - C:\Program Files\nodejs\node.EXE npm: 10.2.4 - C:\Program Files\nodejs\npm.CMD Browsers: Edge: Chromium (120.0.2210.144) Internet Explorer: 11.0.19041.3636 npmPackages: @ampproject/toolbox-optimizer: undefined () @aws-cdk/dns_validated_certificate_handler: 0.0.0 @aws-sdk/client-cognito-identity-provider: ^3.490.0 => 3.490.0 @babel/core: undefined () @babel/runtime: 7.22.5 @edge-runtime/cookies: 4.0.2 @edge-runtime/ponyfill: 2.4.1 @edge-runtime/primitives: 4.0.2 @hapi/accept: undefined () @mswjs/interceptors: undefined () @napi-rs/triples: undefined () @next/font: undefined () @next/react-dev-overlay: undefined () @opentelemetry/api: undefined () @radix-ui/react-avatar: ^1.0.4 => 1.0.4 @radix-ui/react-dialog: ^1.0.5 => 1.0.5 @radix-ui/react-dropdown-menu: ^2.0.6 => 2.0.6 @radix-ui/react-icons: ^1.3.0 => 1.3.0 @radix-ui/react-label: ^2.0.2 => 2.0.2 @radix-ui/react-navigation-menu: ^1.1.4 => 1.1.4 @radix-ui/react-radio-group: ^1.1.3 => 1.1.3 @radix-ui/react-select: ^2.0.0 => 2.0.0 @radix-ui/react-slot: ^1.0.2 => 1.0.2 @radix-ui/react-switch: ^1.0.3 => 1.0.3 @radix-ui/react-tabs: ^1.0.4 => 1.0.4 @segment/ajv-human-errors: undefined () @types/aws-lambda: ^8.10.131 => 8.10.131 @types/node: ^20 => 20.10.8 @types/qrcode: ^1.5.5 => 1.5.5 @types/react: ^18 => 18.2.47 @types/react-dom: ^18 => 18.2.18 @vercel/nft: undefined () @vercel/og: 0.5.15 acorn: undefined () amphtml-validator: undefined () anser: undefined () arg: undefined () assert: undefined () async-retry: undefined () async-sema: undefined () autoprefixer: ^10.0.1 => 10.4.16 aws-amplify: ^6.0.13 => 6.0.13 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/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-cdk-lib: 2.110.1 => 2.110.1 babel-packages: undefined () browserify-zlib: undefined () browserslist: undefined () buffer: undefined () bytes: undefined () ci-info: undefined () class-variance-authority: ^0.7.0 => 0.7.0 cli-select: undefined () client-only: 0.0.1 clsx: ^2.1.0 => 2.1.0 (2.0.0) comment-json: undefined () compression: undefined () conf: undefined () constants-browserify: undefined () constructs: 10.3.0 => 10.3.0 content-disposition: undefined () content-type: undefined () cookie: undefined () cross-spawn: undefined () crypto-browserify: undefined () css.escape: undefined () data-uri-to-buffer: undefined () debug: undefined () devalue: undefined () domain-browser: undefined () dotenv: ^16.3.1 => 16.3.1 edge-runtime: undefined () eslint: ^8 => 8.56.0 eslint-config-next: 14.0.4 => 14.0.4 events: undefined () find-cache-dir: undefined () find-up: undefined () fresh: undefined () get-orientation: undefined () glob: undefined () gzip-size: undefined () http-proxy: undefined () http-proxy-agent: undefined () https-browserify: undefined () https-proxy-agent: undefined () icss-utils: undefined () ignore-loader: undefined () image-size: undefined () is-animated: undefined () is-docker: undefined () is-wsl: undefined () jest-worker: undefined () json5: undefined () jsonwebtoken: undefined () loader-runner: undefined () loader-utils: undefined () lodash.curry: undefined () lru-cache: undefined () lucide-react: ^0.309.0 => 0.309.0 micromatch: undefined () mini-css-extract-plugin: undefined () nanoid: undefined () native-url: undefined () neo-async: undefined () next: 14.0.4 => 14.0.4 node-fetch: undefined () node-html-parser: undefined () ora: undefined () os-browserify: undefined () p-limit: undefined () path-browserify: undefined () platform: undefined () postcss: ^8 => 8.4.33 (8.4.31) 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 () process: undefined () punycode: undefined () qrcode: ^1.5.3 => 1.5.3 querystring-es3: undefined () raw-body: undefined () react: ^18 => 18.2.0 react-builtin: undefined () react-dom: ^18 => 18.2.0 react-dom-builtin: undefined () react-dom-experimental-builtin: undefined () react-experimental-builtin: undefined () react-is: 18.2.0 react-refresh: 0.12.0 react-server-dom-turbopack-builtin: undefined () react-server-dom-turbopack-experimental-builtin: undefined () react-server-dom-webpack-builtin: undefined () react-server-dom-webpack-experimental-builtin: undefined () react-verification-input: ^4.1.0 => 4.1.0 regenerator-runtime: 0.13.4 sass-loader: undefined () scheduler-builtin: undefined () scheduler-experimental-builtin: undefined () schema-utils: undefined () semver: undefined () send: undefined () server-only: 0.0.1 setimmediate: undefined () shell-quote: undefined () source-map: undefined () sst: ^2.39.4 => 2.39.4 stacktrace-parser: undefined () stream-browserify: undefined () stream-http: undefined () string-hash: undefined () string_decoder: undefined () strip-ansi: undefined () superstruct: undefined () tailwind-merge: ^2.2.0 => 2.2.0 tailwindcss: ^3.3.0 => 3.4.1 tailwindcss-animate: ^1.0.7 => 1.0.7 tar: undefined () terser: undefined () text-table: undefined () timers-browserify: undefined () tty-browserify: undefined () typescript: ^5 => 5.3.3 ua-parser-js: undefined () unistore: undefined () util: undefined () vm-browserify: undefined () watchpack: undefined () web-vitals: undefined () webpack: undefined () webpack-sources: undefined () ws: undefined () zod: undefined () npmGlobalPackages: corepack: 0.23.0 npm: 10.2.4 ```

Describe the bug

In short, I'm trying to use the SOFTWARE_TOKEN_MFA flow after successfully completing the CUSTOM_CHALLENGE flow. In my defineAuthChallenge trigger, once the custom challenge is successfully passed, I respond with challengeName = "SOFTWARE_TOKEN_MFA" and issueTokens = false. This successfully returns output.nextStep.signInStep (from auth.signIn) as "CONFIRM_SIGN_IN_WITH_TOTP_CODE", but when I use auth.confirmSignIn, it returns the error "CodeMismatchException - Invalid code or auth state for the user", even though the code is correct.

I'm using SST to launch my backend resources. I've set up password-less authentication (OTP) as described here: https://aws.amazon.com/blogs/mobile/implementing-passwordless-email-authentication-with-amazon-cognito/. I've enabled optional MFA (but I'm only letting users use software tokens, as they can also use their mobiles for OTP).

Expected behavior

I expect that providing the correct code at this stage would grant the user access to their account.

Reproduction steps

  1. Set up a user pool with MFA as optional and software tokens enabled.
  2. Set up a custom auth flow that, after successfully completing, returns event = {response: {challengeName = "SOFTWARE_TOKEN_MFA", issueTokens = false } }
  3. Create a user in the user pool with MFA enabled and TOTP as the preferred method.
  4. Try to sign in with auth.signIn({username, options: {authFlowType: "CUSTOM_WITHOUT_SRP" } })
  5. Complete custom flow (if necessary) (I call auth.confirmSignIn here to return my OTP code)
  6. Upon receiving "CONFIRM_SIGN_IN_WITH_CUSTOM_CHALLENGE" from either auth.signIn or auth.confirmSignIn, call auth.confirmSignIn with the TOTP code
  7. Receive the error described above

Code Snippet

// EXTRACT FROM DEFINE AUTH CHALLENGE TRIGGER

    // If the user provide the correct code
  } else if (event.request.session && event.request.session.length &&
    event.request.session.slice(-1)[0].challengeName === 'CUSTOM_CHALLENGE' && // Doubly stitched, holds better
    event.request.session.slice(-1)[0].challengeResult === true) {

    // Check MFA preferences
    const client = new CognitoIdentityProviderClient();
    try {
      const userOutput = await client.send(
        new AdminGetUserCommand({
          UserPoolId: event.userPoolId,
          Username: event.userName,
        })
      )

      // If MFA enabled, issue a SOFTWARE_TOKEN_MFA challenge
      if (userOutput.PreferredMfaSetting) {
        event.response.challengeName = "SOFTWARE_TOKEN_MFA";
        event.response.issueTokens = false;
      } else {
        // Else, authentication complete
        event.response.issueTokens = true;
      }
      event.response.failAuthentication = false;

      // FUNCTIONS FOR SIGNING IN AND CONFIRMING
      export async function logInWithCognito(options: AuthOptions): Promise<SignInOutput> {
  return await signIn({
    username: options.username!,
    password: !(options.OTP!) ? options.password! : undefined,
    options: {
      authFlowType: !(options.OTP!) ? "USER_SRP_AUTH" : "CUSTOM_WITHOUT_SRP",
    },
  });
}

export async function verifyOTPWithCognito(options: AuthOptions): Promise<SignInOutput> {
  return await confirmSignIn({
    challengeResponse: options.code!,
  })
}

Log output

InitiateAuth payload: ```json { "AuthFlow": "CUSTOM_AUTH", "AuthParameters": { "USERNAME": "campbellborder64@gmail.com" }, "ClientId": "7g4jl3mqd1k8sfmd6qnhekvms6" } ``` and response: ```json {"ChallengeName":"CUSTOM_CHALLENGE","ChallengeParameters":{"USERNAME":"f5946488-ff94-4a28-a9c2-8d98a3019d5e","contact":"campbellborder64@gmail.com"},"Session":"AYABeKab1OyQW_G-T_kG6OCH-EIAHQABAAdTZXJ2aWNlABBDb2duaXRvVXNlclBvb2xzAAEAB2F3cy1rbXMAS2Fybjphd3M6a21zOnVzLWVhc3QtMTo3NDU2MjM0Njc1NTU6a2V5L2IxNTVhZmNhLWJmMjktNGVlZC1hZmQ4LWE5ZTA5MzY1M2RiZQC4AQIBAHgDHnKSW2nDRJSDSLf55TGFyX5On_wV32whMfiMxuCEIAFoV_vxXpQLLgIFj-_wytsAAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM7xRRgSsdNilTcp_GAgEQgDsTrTeUQVwOrUDMVPygJIAwXWK1E3ik2f1fcutGuHt91Z_KlbgKp_doVhnXzTYBlYSlONsaGeL0-jQ87gIAAAAADAAAEAAAAAAAAAAAAAAAAAA7BPG6hqF17irAFYvCOaf3_____wAAAAEAAAAAAAAAAAAAAAEAAAEXL4OysCWMaixexY17bA6Ruk1bBv1uWtwq3apITb2aopVSpFYRFKLBTlNu0YxmotIfAZ-PsveDRQ5iwlNcZwaG_mqGPhaQws3U9KenbFIDa_8pvnbrDnVe7RwfW9TYHcswVg9nrbs90OhdynxosGY64n_5dt3IGexqJ5olUwQMLPCNGZ3JDRcLkv1wnMsNiwMXG-BKAjzyoMQF3md2WGwqgjqEN-446CgNIzJ7yU1-Ub1MUssCyOwy09Mw_p7PR5TyCjaieHZ0wW9nkpNE9XmZekpQCOnCGcXIFzsKZ3J_ohVXiL_GNqClRpXanJPTecVcY-anPZk-j9Xj9VuaF4XpzmUobesyo-qsnwQ5aLoMTyQBbduoLHsUunW9LiDQVuo9F1g6DysLwg"} ``` RespondToAuthChallenge payload (with OTP password): ```json { "ChallengeName": "CUSTOM_CHALLENGE", "ChallengeResponses": { "USERNAME": "f5946488-ff94-4a28-a9c2-8d98a3019d5e", "ANSWER": "372213" }, "Session": "AYABeKab1OyQW_G-T_kG6OCH-EIAHQABAAdTZXJ2aWNlABBDb2duaXRvVXNlclBvb2xzAAEAB2F3cy1rbXMAS2Fybjphd3M6a21zOnVzLWVhc3QtMTo3NDU2MjM0Njc1NTU6a2V5L2IxNTVhZmNhLWJmMjktNGVlZC1hZmQ4LWE5ZTA5MzY1M2RiZQC4AQIBAHgDHnKSW2nDRJSDSLf55TGFyX5On_wV32whMfiMxuCEIAFoV_vxXpQLLgIFj-_wytsAAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM7xRRgSsdNilTcp_GAgEQgDsTrTeUQVwOrUDMVPygJIAwXWK1E3ik2f1fcutGuHt91Z_KlbgKp_doVhnXzTYBlYSlONsaGeL0-jQ87gIAAAAADAAAEAAAAAAAAAAAAAAAAAA7BPG6hqF17irAFYvCOaf3_____wAAAAEAAAAAAAAAAAAAAAEAAAEXL4OysCWMaixexY17bA6Ruk1bBv1uWtwq3apITb2aopVSpFYRFKLBTlNu0YxmotIfAZ-PsveDRQ5iwlNcZwaG_mqGPhaQws3U9KenbFIDa_8pvnbrDnVe7RwfW9TYHcswVg9nrbs90OhdynxosGY64n_5dt3IGexqJ5olUwQMLPCNGZ3JDRcLkv1wnMsNiwMXG-BKAjzyoMQF3md2WGwqgjqEN-446CgNIzJ7yU1-Ub1MUssCyOwy09Mw_p7PR5TyCjaieHZ0wW9nkpNE9XmZekpQCOnCGcXIFzsKZ3J_ohVXiL_GNqClRpXanJPTecVcY-anPZk-j9Xj9VuaF4XpzmUobesyo-qsnwQ5aLoMTyQBbduoLHsUunW9LiDQVuo9F1g6DysLwg", "ClientId": "7g4jl3mqd1k8sfmd6qnhekvms6" } ``` and response: ```json {"ChallengeName":"SOFTWARE_TOKEN_MFA","ChallengeParameters":{},"Session":"AYABeEcH8S7HuWsYHzS8azKEF70AHQABAAdTZXJ2aWNlABBDb2duaXRvVXNlclBvb2xzAAEAB2F3cy1rbXMAS2Fybjphd3M6a21zOnVzLWVhc3QtMTo3NDU2MjM0Njc1NTU6a2V5L2IxNTVhZmNhLWJmMjktNGVlZC1hZmQ4LWE5ZTA5MzY1M2RiZQC4AQIBAHgDHnKSW2nDRJSDSLf55TGFyX5On_wV32whMfiMxuCEIAHdnI7v29Owb5kOco1BFaVkAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMjmBIPBtPYLdM49AHAgEQgDvb1AtZjRkhTMLZcTDoeGIOdmaCiQpyKJoY_eWADQD3DHMzNHr7hHjOp88DMCnwl1RAUOdSICznrlSTigIAAAAADAAAEAAAAAAAAAAAAAAAAACztK2cwvJFQP6ad3jnarmA_____wAAAAEAAAAAAAAAAAAAAAEAAAFboFk4XNAuHBoklavpZMdKZmVEQ4oKAy0HlzVdVAxYWoFuIRsWUuGqNBvxzugJclYQ7p0kESQujxAe_3_ToM0fLDgUDC3Gg6kcJvzuihYbkYwiB_3bhx7gR9Ut8GcFBkdizOZIgL3Bkr2-FJdstXr41pCEtyh9tJtmaILivVg69pcCLZr4lEAfBfP3XxfXzB7KzsfeYjWEqRk6vuBcBbJz94C1oE232UjL5ewKcQDiRoTS2jAJ4-nAPS4k2xkMzsP4jRNsOTWf0eFHqEFgAZ8S1oXg70_4Wb3ST8U-ZqKkm96E0eAG2boZKPCuowHliepTIG9XgS9AM-exNMi6pZRH_9qW2146bhUMWqykerYjzXt2jegVon2dC4NECUxP8MGi42MWBHfjA0nlV4BTuth-itRhUnGpukRXjc6srWqCU5ww2j2qPvDaJL_8bMC3gDs4dGxujWpFBmQzeio1p3hsycEweXOhQLOBYiCc"} ``` RespondToAuthChallenge payload (with MFA code): ```json { "ChallengeName": "SOFTWARE_TOKEN_MFA", "ChallengeResponses": { "USERNAME": "f5946488-ff94-4a28-a9c2-8d98a3019d5e", "SOFTWARE_TOKEN_MFA_CODE": "724188" }, "Session": "AYABeEcH8S7HuWsYHzS8azKEF70AHQABAAdTZXJ2aWNlABBDb2duaXRvVXNlclBvb2xzAAEAB2F3cy1rbXMAS2Fybjphd3M6a21zOnVzLWVhc3QtMTo3NDU2MjM0Njc1NTU6a2V5L2IxNTVhZmNhLWJmMjktNGVlZC1hZmQ4LWE5ZTA5MzY1M2RiZQC4AQIBAHgDHnKSW2nDRJSDSLf55TGFyX5On_wV32whMfiMxuCEIAHdnI7v29Owb5kOco1BFaVkAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMjmBIPBtPYLdM49AHAgEQgDvb1AtZjRkhTMLZcTDoeGIOdmaCiQpyKJoY_eWADQD3DHMzNHr7hHjOp88DMCnwl1RAUOdSICznrlSTigIAAAAADAAAEAAAAAAAAAAAAAAAAACztK2cwvJFQP6ad3jnarmA_____wAAAAEAAAAAAAAAAAAAAAEAAAFboFk4XNAuHBoklavpZMdKZmVEQ4oKAy0HlzVdVAxYWoFuIRsWUuGqNBvxzugJclYQ7p0kESQujxAe_3_ToM0fLDgUDC3Gg6kcJvzuihYbkYwiB_3bhx7gR9Ut8GcFBkdizOZIgL3Bkr2-FJdstXr41pCEtyh9tJtmaILivVg69pcCLZr4lEAfBfP3XxfXzB7KzsfeYjWEqRk6vuBcBbJz94C1oE232UjL5ewKcQDiRoTS2jAJ4-nAPS4k2xkMzsP4jRNsOTWf0eFHqEFgAZ8S1oXg70_4Wb3ST8U-ZqKkm96E0eAG2boZKPCuowHliepTIG9XgS9AM-exNMi6pZRH_9qW2146bhUMWqykerYjzXt2jegVon2dC4NECUxP8MGi42MWBHfjA0nlV4BTuth-itRhUnGpukRXjc6srWqCU5ww2j2qPvDaJL_8bMC3gDs4dGxujWpFBmQzeio1p3hsycEweXOhQLOBYiCc", "ClientId": "7g4jl3mqd1k8sfmd6qnhekvms6" } ``` and response: ```json {"__type":"CodeMismatchException","message":"Invalid code or auth state for the user."} ```

aws-exports.js

No response

Manual configuration

No response

Additional configuration

{
    "UserPool": {
        "Id": "us-east-1_mkWmWkOKR",
        "Name": "dev-prescience-health-Auth",
        "Policies": {
            "PasswordPolicy": {
                "MinimumLength": 6,
                "RequireUppercase": false,
                "RequireLowercase": false,
                "RequireNumbers": false,
                "RequireSymbols": false,
                "TemporaryPasswordValidityDays": 7
            }
        },
        "DeletionProtection": "INACTIVE",
        "LambdaConfig": {
            "PreSignUp": "arn:aws:lambda:us-east-1:482363207483:function:dev-prescience-health-Aut-TriggerPreSignUp443BADF6-aF4uOIj7AS3U",
            "DefineAuthChallenge": "arn:aws:lambda:us-east-1:482363207483:function:dev-prescience-health-Aut-TriggerDefineAuthChallen-yV4LMh54Hu16",
            "CreateAuthChallenge": "arn:aws:lambda:us-east-1:482363207483:function:dev-prescience-health-Aut-TriggerCreateAuthChallen-kqRFQMYHsmDY",
            "VerifyAuthChallengeResponse": "arn:aws:lambda:us-east-1:482363207483:function:dev-prescience-health-Aut-TriggerVerifyAuthChallen-ecUBVDfC0HIW",
            "PreTokenGeneration": "arn:aws:lambda:us-east-1:482363207483:function:dev-prescience-health-Aut-TriggerPreTokenGeneratio-vAlGDUCyYRq9",
            "PreTokenGenerationConfig": {
                "LambdaVersion": "V1_0",
                "LambdaArn": "arn:aws:lambda:us-east-1:482363207483:function:dev-prescience-health-Aut-TriggerPreTokenGeneratio-vAlGDUCyYRq9"
            }
        },
        "LastModifiedDate": "2024-01-24T08:48:28.897000+10:00",
        "CreationDate": "2024-01-24T08:48:28.658000+10:00",
        "SchemaAttributes": [
            {
                "Name": "sub",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": false,
                "Required": true,
                "StringAttributeConstraints": {
                    "MinLength": "1",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "name",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "given_name",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "family_name",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "middle_name",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "nickname",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "preferred_username",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "profile",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "picture",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "website",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "email",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "email_verified",
                "AttributeDataType": "Boolean",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false
            },
            {
                "Name": "gender",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "birthdate",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "10",
                    "MaxLength": "10"
                }
            },
            {
                "Name": "zoneinfo",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "locale",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "phone_number",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "phone_number_verified",
                "AttributeDataType": "Boolean",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false
            },
            {
                "Name": "address",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "updated_at",
                "AttributeDataType": "Number",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "NumberAttributeConstraints": {
                    "MinValue": "0"
                }
            },
            {
                "Name": "custom:hasPassword",
                "AttributeDataType": "Boolean",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false
            },
            {
                "Name": "custom:preferredOTPMethod",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {}
            },
            {
                "Name": "identities",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {}
            }
        ],
        "AutoVerifiedAttributes": [
            "email",
            "phone_number"
        ],
        "UsernameAttributes": [
            "email",
            "phone_number"
        ],
        "SmsVerificationMessage": "The verification code to your new account is {####}",
        "EmailVerificationMessage": "The verification code to your new account is {####}",
        "EmailVerificationSubject": "Verify your new account",
        "VerificationMessageTemplate": {
            "SmsMessage": "The verification code to your new account is {####}",
            "EmailMessage": "The verification code to your new account is {####}",
            "EmailSubject": "Verify your new account",
            "DefaultEmailOption": "CONFIRM_WITH_CODE"
        },
        "UserAttributeUpdateSettings": {
            "AttributesRequireVerificationBeforeUpdate": [
                "phone_number",
                "email"
            ]
        },
        "MfaConfiguration": "OPTIONAL",
        "EstimatedNumberOfUsers": 1,
        "EmailConfiguration": {
            "EmailSendingAccount": "COGNITO_DEFAULT"
        },
        "SmsConfiguration": {
            "SnsCallerArn": "arn:aws:iam::482363207483:role/dev-prescience-health-Aut-AuthUserPoolsmsRole664FB2-mLtzX1qyGLp4",
            "ExternalId": "devpresciencehealthAuthStackAuthUserPool48808BDC",
            "SnsRegion": "us-east-1"
        },
        "UserPoolTags": {
            "sst:app": "prescience-health",
            "sst:stage": "dev"
        },
        "SmsConfigurationFailure": "SNSSandbox",
        "Domain": "presciencehealth-dev",
        "AdminCreateUserConfig": {
            "AllowAdminCreateUserOnly": false,
            "UnusedAccountValidityDays": 7
        },
        "UsernameConfiguration": {
            "CaseSensitive": false
        },
        "Arn": "arn:aws:cognito-idp:us-east-1:482363207483:userpool/us-east-1_mkWmWkOKR",
        "AccountRecoverySetting": {
            "RecoveryMechanisms": [
                {
                    "Priority": 1,
                    "Name": "verified_phone_number"
                },
                {
                    "Priority": 2,
                    "Name": "verified_email"
                }
            ]
        }
    }
}

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

nadetastic commented 5 months ago

Hi @campbellborder thank you for opening this issue. I've been taking alook at this and I'm able to reproduce the same behavior as well. Im currently discussing with the Cognito team, mainly because in the documentation shown here, it seems that SOFTWARE_TOKEN_MFA is not an expected challengeName.

I will follow up soon with an update, but in the meantime, let me know if you have any questions.

nadetastic commented 4 months ago

Hi @campbellborder following up here. After discussing with the Cognito team, the issue here is that MFA is not supported when using passwordless authentication flows within a Custom Auth Flow, as MFA generation is dependent on the password verifier challenge being triggered. As an alternative, you can configure and add a custom challenge where you send you user an OTP, using Amazon Pinpoint for example - more on Pinpoint for OTP can be found tin the documentation here.

Let me know if you have any questions, and in the meantime we will mark this as a feature request for the Cognito team.

campbellborder commented 4 months ago

Hi @nadetastic, thanks for looking into this. My issue is that my custom auth flow is an OTP challenge, so doesn't make sense to use OTP as the MFA method as well. Is there any way to use MFA token apps as a custom auth flow? Otherwise will just have to wait for the feature request to be completed. Cheers!

campbellborder commented 1 day ago

Hi - any update on this?