I am trying to implement a basic Cognito migration lambda moving users from Auth0 to Cognito. I am aware there have been many questions on this already. I have reviewed all the questions & answers I think are relevant but have not found a solution. The ones I have looked at are:
- AWS Cognito User Migration Trigger not working
- User Migration to Cognito using Lambda trigger in python
I have followed the basic example in the tutorial here. Code:
index.ts
import { Handler, UserMigrationTriggerEvent } from "aws-lambda"
import axios from "axios"
import { Auth0User, Auth0UserInfo} from "./interfaces.js"
function getUserAttributes(user: Auth0UserInfo | Auth0User) {
return {
email: user.email,
// Required for standard migration but also forgotten password
// flow to enable password-reset code to be sent to user
email_verified: "true",
name: user.name,
given_name: user.given_name,
family_name: user.family_name,
updated_at: user.updated_at
}
}
export const handler: Handler = async (event: UserMigrationTriggerEvent): Promise<UserMigrationTriggerEvent> => {
try {
const { AUTH0_MANAGEMENT_CLIENT_ID, AUTH0_MANAGEMENT_CLIENT_SECRET, AUTH0_TENANT_URL } = process.env
if (AUTH0_MANAGEMENT_CLIENT_ID && AUTH0_MANAGEMENT_CLIENT_SECRET && AUTH0_TENANT_URL) {
if (event.triggerSource === "UserMigration_Authentication" && event.userName && event.request.password) {
const userInfo = await authenticateWithAuth0AndGetUserInfo(event.userName, event.request.password)
if (userInfo) {
console.log(`User Info: ${JSON.stringify(userInfo)}`)
event.response.userAttributes = getUserAttributes(userInfo)
event.response.finalUserStatus = "CONFIRMED"
event.response.messageAction = "SUPPRESS"
}
} else if (event.triggerSource === "UserMigration_ForgotPassword" && event.userName) {
const user = await lookupUserWithAuth0(event.userName)
if (user) {
event.response.userAttributes = getUserAttributes(user)
event.response.messageAction = "SUPPRESS"
}
}
}
console.log(`Response: ${JSON.stringify(event)}`)
return event
} catch(err: any) {
throw err
}
}
Logging out the event at the end just to check a valid response which seems correct:
{
"version": "1",
"triggerSource": "UserMigration_Authentication",
"region": "eu-west-1",
"userPoolId": "<userPoolId>",
"userName": "<userName>",
"callerContext": {
"awsSdkVersion": "aws-sdk-unknown-unknown",
"clientId": "<clientId>"
},
"request": {
"password": "<password>",
"validationData": null,
"userAttributes": null
},
"response": {
"userAttributes": {
"email": "<email>",
"email_verified": "true",
"name": "<name>",
"given_name": "<given_name>",
"family_name": "<family_name>",
"updated_at": "<updated_at>"
},
"forceAliasCreation": null,
"enableSMSMFA": null,
"finalUserStatus": "CONFIRMED",
"messageAction": "SUPPRESS",
"desiredDeliveryMediums": null
}
}
I have tried returning the event or doing context.succeed (now deprecated) & neither work. The required properties on the user pool (which are all being populated) are:
- name
- updated_at
I have also tried altering email_verified from a string to a boolean & still doesn't work.
I have attempted adding username to the userAttributes which shouldn't be required as nothing else is aliased but that doesn't work either.
The app client doesn't have a client secret & it allows the "USER_PASSWORD_AUTH" flow.
Runtime is NodeJS v18.
The Hosted UI always returns:
"Incorrect username or password"
EDIT
I have been reading this article as it seems newer. It describes adding the username to the userAttributes which I have done but still does not work. I have also looked at this troubleshooting guide which recommends to attempt the migrate via the CLI which I have done with:
aws cognito-idp initiate-auth --client-id <clientId> --auth-flow USER_PASSWORD_AUTH --auth-parameters "USERNAME=<username>,PASSWORD=<password>"
Which gives me the same error:
An error occurred (NotAuthorizedException) when calling the InitiateAuth operation: Incorrect username or password.
Passing the --debug option doesn't seem to provide anymore insight either.