Skip to content

Cognito Migration Trigger returns an event, but Cognito fails to create user

0

Hello,

I have a Lambda to migrate users from the old user pool to a new one. The lambda is being triggered and executes successfully. It returns the following event:

{
    "version": "1",
    "triggerSource": "UserMigration_Authentication",
    "region": "us-east-1",
    "userPoolId": "us-east-ID",
    "userName": "email...",
    "callerContext": {
        "awsSdkVersion": "aws-sdk-unknown-unknown",
        "clientId": "client-ID-uuid"
    },
    "request": {
        "password": "qwerty123",
        "validationData": null,
        "userAttributes": null
    },
    "response": {
        "userAttributes": {
            "sub": "3d1d50ef-ad51-4acd-a9bf-111111111111",
            "custom:country": "CA",
            "website": "site_url",
            "address": "Street",
            "email_verified": "true",
            "custom:company_name": "Corporate Inc.",
            "phone_number_verified": "false",
            "custom:employees_num": "1-50",
            "given_name": "John",
            "custom:company_type": "Business.",
            "custom:position": "CEO.",
            "phone_number": "number",
            "family_name": "Wick",
            "email": "email...",
            "name": "3d1d50ef-ad51-4acd-a9bf-111111111111",
            "custom:company_id": "7c1f44ab-341a-4423-9b7e-222222222",
            "custom:role": "Owner"
        },
        "forceAliasCreation": null,
        "enableSMSMFA": null,
        "finalUserStatus": "CONFIRMED",
        "messageAction": "SUPPRESS",
        "desiredDeliveryMediums": null
    }
}

The pool's mandatory attributes are website, email, given_name, and family_name.

Once I try to login with the to-be-migrated user I get "Invalid input: Incorrect username or password."

The CloudTrail logs contain the following:

{
    "eventVersion": "1.10",
    "userIdentity": {
        "type": "Unknown",
        "accountId": "<accountId>"
    },
    "eventTime": "2025-03-10T06:25:11Z",
    "eventSource": "cognito-idp.amazonaws.com",
    "eventName": "login_POST",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "IP",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
    "errorCode": "400",
    "errorMessage": "Unexpected exception",
    "requestParameters": null,
    "responseElements": null,
    "additionalEventData": {
        "managedLoginBrandingVersion": 2,
        "requestParameters": {
            "client_id": "client-ID-uuid",
            "redirect_uri": "http://localhost:3000",
            "response_type": "code",
            "scope": "<REDACTED>",
            "state": "<REDACTED>",
            "code_challenge": "<REDACTED>",
            "code_challenge_method": "<REDACTED>",
            "_data": "<REDACTED>"
        },
        "userPoolDomain": "auth.example.com",
        "responseParameters": {
            "status": 400
        },
        "userPoolId": "us-east-ID",
        "clientId": "client-ID-uuid"
    },
    "requestID": <UUID>",
    "eventID": "<UUID>",
    "readOnly": false,
    "resources": [
        {
            "type": "AWS::Cognito::UserPool",
            "ARN": "arn:aws:cognito-idp:us-east-1:<accountID>:userpool/us-east-ID"
        }
    ],
    "eventType": "AwsServiceEvent",
    "managementEvent": true,
    "recipientAccountId": "<accountID>",
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "clientProvidedHostHeader": "url"
    }
}

Here's my pool and client definition:

  CognitoUserPool:
    Type: "AWS::Cognito::UserPool"
    Properties:
      UserPoolName: !Ref UserPoolName
      UserPoolTier: ESSENTIALS
      Policies:
        PasswordPolicy:
          MinimumLength: 8
          RequireUppercase: true
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: true
          TemporaryPasswordValidityDays: 7
      LambdaConfig:
        PreSignUp: !If
          - ShouldAddPreSignUpLambda
          - !Ref PreSignUpLambdaArn
          - !Ref "AWS::NoValue"
        PostConfirmation: !If
          - ShouldAddPostSignUpLambda
          - !Ref PostSignUpLambdaArn
          - !Ref "AWS::NoValue"
        PreTokenGenerationConfig: !If
          - ShouldAddPreTokenGenerationLambda
          - LambdaArn: !Ref PreTokenGenerationLambdaArn
            LambdaVersion: !If
              - ShouldAddPreTokenGenerationVersion
              - !Ref PreTokenGenerationLambdaVersion
              - "v2_0"
          - !Ref "AWS::NoValue"
        UserMigration: !If
          - ShouldAddMigrationLambda
          - !Ref MigrationLambdaArn
          - !Ref "AWS::NoValue"
      Schema:
        # https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-custom-attributes.html
        - Name: "email"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "0"
            MaxLength: "2048"
        - Name: "given_name"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: true
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "2048"
        - Name: "family_name"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: true
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "2048"
        - Name: "website"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: true
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "512"
        - Name: "company_name"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "2048"
        - Name: "company_type"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "3"
            MaxLength: "1024"
        - Name: "company_id"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "32"
            MaxLength: "36"
        - Name: "position"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "512"
        - Name: "employees_num"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "128"
        - Name: "country"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "256"
        - Name: "address"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "2048"
        - Name: "birthdate"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "10"
            MaxLength: "10"
        - Name: "username"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "3"
            MaxLength: "128"
        - Name: "locale"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "256"
        - Name: "middle_name"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "256"
        - Name: "phone_number"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "9"
            MaxLength: "12"
        - Name: "picture"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "512"
        - Name: "profile"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "512"
        - Name: "updated_at"
          AttributeDataType: "Number"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          NumberAttributeConstraints:
            MinValue: "0"
        - Name: "zoneinfo"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "1"
            MaxLength: "256"
        - Name: "role"
          AttributeDataType: "String"
          DeveloperOnlyAttribute: false
          Mutable: true
          Required: false
          StringAttributeConstraints:
            MinLength: "4"
            MaxLength: "256"
      AccountRecoverySetting:
        RecoveryMechanisms:
          - Name: "verified_email"
            Priority: 1
      AutoVerifiedAttributes:
        - "email"
      UsernameAttributes:
        - "email"
      MfaConfiguration: "OFF"

  CognitoUserPoolClient:
    Type: "AWS::Cognito::UserPoolClient"
    Properties:
      UserPoolId: !Ref CognitoUserPool
      ClientName: "website"
      GenerateSecret: false
      RefreshTokenValidity: 30
      # https://forum.serverless.com/t/cant-set-writeable-or-readable-properties-on-user-pool-client/2566
      ReadAttributes:
        - address
        - email
        - email_verified
        - family_name
        - given_name
        - website
        - phone_number
        - phone_number_verified
        - "custom:company_name"
        - "custom:company_id"
        - "custom:company_type"
        - "custom:position"
        - "custom:employees_num"
        - "custom:country"
        - "custom:role"
        - updated_at
      WriteAttributes:
        - address
        - email
        - family_name
        - given_name
        - website
        - phone_number
        - "custom:company_name"
        - "custom:company_id"
        - "custom:company_type"
        - "custom:position"
        - "custom:employees_num"
        - "custom:role"
        - "custom:country"
      ExplicitAuthFlows:
        - "ALLOW_CUSTOM_AUTH"
        - "ALLOW_REFRESH_TOKEN_AUTH"
        - "ALLOW_USER_PASSWORD_AUTH"
        - "ALLOW_USER_SRP_AUTH"
      PreventUserExistenceErrors: "ENABLED"
      SupportedIdentityProviders:
        - "COGNITO"
        - !Ref CognitoUserPoolIdentityProvider
      CallbackURLs:
        - "http://localhost:3000"
        - !Sub "https://${MainDomainName}"
      LogoutURLs:
        - "http://localhost:3000"
        - !Sub "https://${MainDomainName}"
      AllowedOAuthFlows:
        - "code"
      AllowedOAuthScopes:
        - "email"
        - "openid"
        - "phone"
        - "profile"
      AllowedOAuthFlowsUserPoolClient: true
      IdTokenValidity: 1
      AccessTokenValidity: 60
      TokenValidityUnits:
        AccessToken: "minutes"
        IdToken: "days"
        RefreshToken: "days"

Lambda execution time is 300 ms, allocated memory: 512 Mb, consumed memory: 120 Mb. The error is very confusing. What does "Unexpected error" even mean? Are there expected errors? I checked everything and it is still not clear what's the issue here.

asked 2 years ago382 views

2 Answers
1
Accepted Answer

I did 2 things to fix it:

  • First: email was listed as a required attribute, but also UsernameAttributes was set to email causing the overlap. I removed UsernameAttributes to let Cognito do it automatically.
  • My lambda was returning the "sub" attribute, which shouldn't be the case. I filtered the attributes and the issue disappeared.

I was able to fix it, but the experience isn't the best. I think AWS team should do a proper error handling on Cognito side to provide some meaningful debug information. Unexpected error is the same as "Something went wrong", it doesn't help at all but only complicates things.

answered 2 years ago

EXPERT

reviewed 2 years ago

-2

Based on the information provided, there are a few potential reasons why Cognito is failing to create the user despite the Lambda trigger executing successfully:

  1. Attribute Mismatch: Ensure that all required attributes for the new user pool are properly mapped in the Lambda response. You mentioned that website, email, given_name, and family_name are mandatory attributes. Double-check that these are correctly included in the userAttributes of the Lambda response.

  2. Username Handling: Cognito uses the 'userName' field as the unique identifier. Make sure the 'userName' in the event matches the email address you're using to log in, as it appears you're using email as the username.

  3. Password Handling: The migration trigger doesn't actually migrate the password. Instead, it should validate the password against your old system and then allow Cognito to set a new password. Make sure your Lambda is correctly validating the password.

  4. Attribute Formatting: Ensure that all attribute values are strings. For example, 'email_verified' and 'phone_number_verified' should be "true" or "false" as strings, not boolean values.

  5. Custom Attributes: Verify that all custom attributes (those prefixed with 'custom:') are properly defined in your new Cognito user pool before attempting to migrate users with those attributes.

  6. Error Handling: Your Lambda function should handle and log any errors it encounters. Check your Lambda logs for any error messages that might not be visible in the Cognito logs.

  7. User Status: The 'finalUserStatus' is set to 'CONFIRMED', which is correct, but ensure this matches your desired configuration in the new user pool.

  8. Message Suppression: You're suppressing the welcome message with 'messageAction': 'SUPPRESS'. This is fine, but make sure it aligns with your intended user experience.

To troubleshoot further:

  1. Double-check all attribute mappings and ensure they match exactly with the new user pool's configuration.
  2. Verify that the Lambda has the necessary permissions to interact with Cognito.
  3. Try enabling detailed CloudWatch logs for both the Lambda function and Cognito to get more insight into what's happening during the migration process.
  4. Consider temporarily removing any non-essential attributes from the migration process to isolate the issue.

If the problem persists, you may need to implement more detailed error logging in your Lambda function to pinpoint exactly where the migration is failing.
Sources
Migrate user Lambda trigger - Amazon Cognito
Why is Cognito not migrating users from my Django RDS Aurora DB to Cognito User Pool? | AWS re:Post

answered 2 years ago

EXPERT

reviewed 2 years ago

  • Unfortunately, nothing helps. I can't find the problem.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.