Migrating AWS Cognito Users Into Auth0

There are two ways to import users into Auth0:

  1. Bulk Migration
  2. Automatic Migration (i.e. Lazy Load)

Currently, there is really no easy way to export users out of AWS Cognito. And even if you did, the exported user profile would not include the user’s hashed password so it would require that the user reset their account password once migrated to Auth0 as the identity provider. Not ideal. So bulk migration is kind of out of the question.

Instead, Automatic Migration is probably the way to go. You must configure a Custom Database in Auth0 and point it to your AWS Cognito user pool and define two scripts: one to get a user and another to login a user.

AWS doesn’t expose these endpoints via an API by default, but they do have similar functions in their amazon-cognito-identity-js npm package (according to Scenario 4 in the documentation).

You can use this npm package in the Auth0 Custom Database get-user and login scripts to perform automatic migration. Just make sure you check the Import Users to Auth0 to true under the Custom Database settings.

get-user.js

/*
Requires Auth0 Global Variables to be set - https://auth0.com/docs/rules/configure-global-variables-for-rules
If testing locally (or not wanting to use Auth0 Global Variables):
const configuration = {
  "accessKeyId": "AKIAIBDT5G4M237CZSMQ",
  "secretAccessKey": "your-cognito-secret-access-key",
  "region": "eu-west-1",
  "UserPoolId": "eu-west-1_V69pvauTp"
*/

function getUser(username, callback) {
    const userParameters =  ["email", "email_verified", "custom:designation"];
    const AWS = require('aws-sdk@2.593.0');
    AWS.config.update({ "accessKeyId": configuration.accessKeyId, "secretAccessKey": configuration.secretAccessKey, "region": configuration.region });
    const cognito = new AWS.CognitoIdentityServiceProvider();

    cognito.adminGetUser({
        UserPoolId: configuration.UserPoolId,
        Username: username
    }, (err, data) => {
        if (err) {
            console.log(err);
            if (err.code === "UserNotFoundException") return callback(null);
            else callback(err);
        }
        else {
            console.log(data);
            if (data.code === "UserNotFoundException") return callback(null);
            else {
                let profile = {
                    "user_id": data.UserAttributes.find(item=>item.Name==="sub").Value,
                    "username": data.Username,
                };
                userParameters.forEach(customParameterName => {
                    profile[customParameterName] = data.UserAttributes.find(item=>item.Name===customParameterName).Value;
                });
                return callback(null, profile);
            }
        }

    });

}

login.js

/*
Read StackOverflow article about potential window issue: https://stackoverflow.com/questions/40219518/aws-cognito-unauthenticated-login-error-window-is-not-defined-js

Requires Auth0 Global Variables to be set - https://auth0.com/docs/rules/configure-global-variables-for-rules

If testing locally (or not wanting to use Auth0 Global Variables):
const configuration = {
  "ClientId": "nzHNdG0XGS4qSaS5p0EZZesoIO2xfKQDRMgWPoce",
  "UserPoolId": "eu-west-1_V69pvauTp"
*/

function login(username, password, callback) {
    global.fetch = require('node-fetch@2.6.0');
    var AmazonCognitoIdentity = require('amazon-cognito-identity-js@3.0.14');
    var poolData = {
        UserPoolId: configuration.UserPoolId,
        ClientId: configuration.ClientId

    };
    var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);

    var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails({
        Username: username,
        Password: password
    });
    var userData = {
        Username: username,
        Pool: userPool
    };
    var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
    cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: function (result) {
            //console.log(result);
            var idTokenPayload = result.getIdToken().payload;
            console.log(idTokenPayload);
            var profile = {
              user_id: idTokenPayload.sub,
              email: idTokenPayload.email,
              /* might want to set this to false if you're not validating email addresses */
              email_verified: true,
            };
            console.log({ result, idTokenPayload, profile });
            callback(null, profile);
        },
        onFailure: (function (err) {
            return callback(new WrongUsernameOrPasswordError(username))
        })
    });
}
3 Likes