AWS cognito user migration pool trigger not working on login flow

依然范特西╮ 提交于 2021-02-07 10:19:51

问题


I am using AWS cognito pool migration using Lambda function with cognito execution role Following is my new pool app client setting

or

AWS doc says

User migration authentication flow A user migration Lambda trigger allows easy migration of users from a legacy user management system into your user pool. To avoid making your users reset their passwords during user migration, choose the USER_PASSWORD_AUTH authentication flow. This flow sends your users' passwords to the service over an encrypted SSL connection during authentication.

When you have completed migrating all your users, we recommend switching flows to the more secure SRP flow. The SRP flow does not send any passwords over the network.

I have created lambda function with role "AmazonCognitoPowerUser"

        async function authenticateUser(cognitoISP: CognitoIdentityServiceProvider, username: string, password: string): Promise<User | undefined> {
            console.log(`authenticateUser: user='${username}'`);

            const params: AdminInitiateAuthRequest = {
                AuthFlow: 'ADMIN_USER_PASSWORD_AUTH',
                AuthParameters: {
                    PASSWORD: password,
                    USERNAME: username,
                },
                ClientId: OLD_CLIENT_ID,
                UserPoolId: OLD_USER_POOL_ID,
            };
            const cognitoResponse = await cognitoISP.adminInitiateAuth(params).promise();
            const awsError: AWSError = cognitoResponse as any as AWSError;
            if (awsError.code && awsError.message) {
                console.log(`authenticateUser: error ${JSON.stringify(awsError)}`);
                return undefined;
            }
            console.log(`authenticateUser: found ${JSON.stringify(cognitoResponse)}`);

            return lookupUser(cognitoISP, username);
        }

        async function lookupUser(cognitoISP: CognitoIdentityServiceProvider, username: string): Promise<User | undefined> {
            console.log(`lookupUser: user='${username}'`);
            const params = {
                UserPoolId: OLD_USER_POOL_ID,
                Username: username,
            };
            const cognitoResponse = await cognitoISP.adminGetUser(params).promise();
            const awsError: AWSError = cognitoResponse as any as AWSError;
            if (awsError.code && awsError.message) {
                console.log(`lookupUser: error ${JSON.stringify(awsError)}`);
                return undefined;
            }
            console.log(`lookupUser: found ${JSON.stringify(cognitoResponse)}`);

            const userAttributes = cognitoResponse.UserAttributes ? cognitoResponse.UserAttributes.reduce((acc, entry) => ({
                ...acc,
                [entry.Name]: entry.Value,
            }), {} as {[key: string]: string | undefined}) : {};
            const user: User = {
                userAttributes,
                userName: cognitoResponse.Username,
            };
            console.log(`lookupUser: response ${JSON.stringify(user)}`);
            return user;
        }

        async function onUserMigrationAuthentication(cognitoISP: CognitoIdentityServiceProvider, event: CognitoUserPoolTriggerEvent) {
            // authenticate the user with your existing user directory service
            const user = await authenticateUser(cognitoISP, event.userName!, event.request.password!);
            if (!user) {
                throw new Error('Bad credentials');
            }

            event.response.userAttributes = {
                // old_username: user.userName,
                // 'custom:tenant': user.userAttributes['custom:tenant'],
                email: user.userAttributes.email!,
                email_verified: 'true',
                preferred_username: user.userAttributes.preferred_username!,
            };
            event.response.finalUserStatus = 'CONFIRMED';
            event.response.messageAction = 'SUPPRESS';

            console.log(`Authentication - response: ${JSON.stringify(event.response)}`);
            return event;
        }

        async function onUserMigrationForgotPassword(cognitoISP: CognitoIdentityServiceProvider, event: CognitoUserPoolTriggerEvent) {
            // Lookup the user in your existing user directory service
            const user = await lookupUser(cognitoISP, event.userName!);
            if (!user) {
                throw new Error('Bad credentials');
            }

            event.response.userAttributes = {
                // old_username: user.userName,
                // 'custom:tenant': user.userAttributes['custom:tenant'],
                email: user.userAttributes.email!,
                email_verified: 'true',
                preferred_username: user.userAttributes.preferred_username!,
            };
            event.response.messageAction = 'SUPPRESS';

            console.log(`Forgot password - response: ${JSON.stringify(event.response)}`);

            return event;
        }

        export const handler = async (event: CognitoUserPoolTriggerEvent, context: Context): Promise<CognitoUserPoolTriggerEvent> => {
            const options: CognitoIdentityServiceProvider.Types.ClientConfiguration = {
                region: OLD_USER_POOL_REGION,
            };
            if (OLD_ROLE_ARN) {
                options.credentials = new ChainableTemporaryCredentials({
                    params: {
                        ExternalId: OLD_EXTERNAL_ID,
                        RoleArn: OLD_ROLE_ARN,
                        RoleSessionName: context.awsRequestId,
                    },
                });
            }
            const cognitoIdentityServiceProvider = new CognitoIdentityServiceProvider(options);

            switch (event.triggerSource) {
                case 'UserMigration_Authentication':
                    return onUserMigrationAuthentication(cognitoIdentityServiceProvider, event);
                case 'UserMigration_ForgotPassword':
                    return onUserMigrationForgotPassword(cognitoIdentityServiceProvider, event);
                default:
                    throw new Error(`Bad triggerSource ${event.triggerSource}`);
            }
        }

and added trigger into new pool,

After many attempt Lambda trigger is not working on login always getting error .

  {__type: "NotAuthorizedException", message: "Incorrect username or password."}
       message: "Incorrect username or password."
     __type: "NotAuthorizedException"

Though its working fine if we use forget passwords flow after reset password user migrated to new pool

  • https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-import-using-lambda.html

UPDATED :

When directly run test on lambda using following json

  {
   "version": "1",
   "triggerSource": "UserMigration_Authentication",
   "region": "ap-south-1",
   "userPoolId": "ap-XXXXXXXXX2",
   "userName": "vaquar.test@gmail.com",
   "callerContext": {
   "awsSdkVersion": "aws-sdk-unknown-unknown",
   "clientId": "1XXXXXXXXXXXXXXXXXXfgk"
   },
   "request": {
   "password": "vkhan",
   "validationData": null,
   "userAttributes": null
    },
   "response": {
    "userAttributes": null,
    "forceAliasCreation": null,
    "finalUserStatus": null,
    "messageAction": null,
    "desiredDeliveryMediums": null
    }
  }

Then getting following response and user migrated into new pool means we have issue in trigger during login.

 INFO   Authentication - response: {"userAttributes":{"email":"vaquar.test@gmail.com","email_verified":"true"},"forceAliasCreation":null,"finalUserStatus":"CONFIRMED","messageAction":"SUPPRESS","desiredDeliveryMediums":null}

回答1:


With Lambda trigger, Cognito service invokes Lambda function. So Cognito will require permission to invoke Lambda function. How are you configuring the Lambda trigger on your userpool? If you are using AWS Cognito console, the permission should be set automatically.

You may also verify if the user already exists in the new userpool that could cause such behavior.



来源:https://stackoverflow.com/questions/62355507/aws-cognito-user-migration-pool-trigger-not-working-on-login-flow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!