Here’s the stripped version of the postLogin action. This postLogin action is responsible for merging accounts for universal login and passwordless login.
exports.onExecutePostLogin = async (event, api) => {
const _ = require('lodash');
const async = require('async');
const axios = require('axios').default;
const ManagementClient = require('auth0').ManagementClient;
const management = new ManagementClient({
clientId: event.secrets.AUTH0_APP_CLIENT_ID,
clientSecret: event.secrets.AUTH0_APP_CLIENT_SECRET,
domain: event.secrets.AUTH0_DOMAIN
});
// Lookup Users by Email within Auth0 and External DB
async.parallel({
auth0: function(cb) {
management.usersByEmail.getByEmail(
{ email: event.user.email }
).then(response => {
cb(null, response.data);
}).catch(err => {
cb(`ERROR: ${JSON.parse(err.body)['message']}`, null);
});
},
external: function(cb) {
var options = {
method: 'GET',
url: `${event.secrets.TARGET_DOMAIN}/api/users/lookup`,
params: {email: event.user.email},
headers: {authorization: `Bearer ***`},
validateStatus: () => true
};
// External DB Lookup
axios.request(options).then(async function (response) {
if(response.status === 200) {
console.log("Lookup: User found!");
cb(null, response.data);
} else if (response.status === 404) {
try {
var createdUser = await createUser();
cb(null, createdUser);
} catch (error) {
cb(error, response.data);
}
} else {
cb(new Error("Error Requesting User Profile!"), response.data);
}
}).catch(function (err) {
cb(new Error(`ERROR - User Lookup: ${err}`), null);
});
}
}, async function(err, results) {
// Break on Errors Requesting Data
if(err) {
console.error("Error Requesting User Profile Data: " + err);
return;
}
if ([1, 2].includes(results.auth0.length)) {
// Add external user id to user_metadata
api.user.setUserMetadata('external_user_id', results.external.user.id);
// Workflow: Single Auth0 User Found - Merger Not Needed
if (results.auth0.length === 1) {
console.log('Single Auth0 User Found - Merger Not Needed');
return;
}
} else if (results.auth0.length === 0) {
// Workflow: Auth0 User Not Found
console.log('Auth0 user not found.');
return;
} else if (results.auth0.length > 2) {
// Workflow: Manual Work Needed to Merge Account - Over 2 Auth0 Account Exist
console.log('Rule: Multiple User Profiles Already Exist');
return;
}
// Collect identities
var identities = [];
_.forEach(results.auth0, function(e) {
_.forEach(e.identities, function(u) {
var merged = u;
merged.auth0_id = e.user_id;
merged.created_at = new Date(e.created_at).getTime();
merged.updated_at = new Date(e.updated_at).getTime();
identities.push(merged);
});
});
// Determine Base Auth0 User Account - Base User should be Provider: Auth0
identities = _.sortBy(identities, ['created_at']);
var baseIdentity = _(identities).filter({'provider': 'auth0'}).first();
// Determine if current user is the base identity
if (event.user.user_id === baseIdentity.auth0_id) {
var secondIdentity = _(identities).filter({'provider': 'email'}).first();
// Link secondary (email) to base identity (auth0 provider)
management.users.link(
{ id: baseIdentity.auth0_id },
{ provider: secondIdentity.provider, user_id: secondIdentity.auth0_id }
).then(data => {
console.log('Link User (1) - Successful');
}
).catch(err => {
console.log(`Link User (1) - ERROR: ${err}`);
});
} else {
var userIdentity = _(event.user.identities).first();
// Prevent account-linking for users using the same email address but does not match with
// the base identity connection. Except for email connection (passwordless).
if(userIdentity.connection != 'email' && userIdentity.connection !== baseIdentity.connection) {
console.log('Connection did not match the base identity connection. Skipping.');
return;
}
// Link current user to base identity (auth0 provider)
management.users.link(
{ id: baseIdentity.auth0_id },
{ provider: userIdentity.provider, user_id: userIdentity.user_id }
).then(data => {
console.log('Link User (2) - Successful');
}
).catch(err => {
console.log(`Link User (2) - ERROR: ${err}`);
});
}
});
};
Again, thank you so much for attending to my issue. Really appreciated it.