I installed the Account Link extension which enables to link existing Database accounts to Social or Enterprise accounts. This works very well. I have disabled Sign up for database accounts so I can manually Create Users only from dashboard, then I can attempt to login with an existing Social Login (in this case only Google) or a configured Enterprise login ( Microsoft Azure AD) and right away is asked to link them.
The problem is when I try to Login with Social Login (Google) is created a user in Auth0 dashboard that allows it to get in, since there’s no registered user also there is no link account screen. I don’t want that, no google login should be allowed if there is no existing Database account related first.
I thought that a ‘Disable Social Sign ups’ rule was the choice, but after enabling it I’m not able to link it with a existing email! It’s denying any attempt to Login with Google, registered or not.
How can I set a rule to allow registered Database users to link their accounts to google seamlessly ?
Let them register with Facebook first, but then check within a rule if they already have another identity for a database connection, and if not, redirect them to a page where you require them to set a password, upon which you would then create and link that user in the database connection via a call to the Management API.
(Initially I had the idea to use a pre-user-registration hook and check if the user has an existing account under his email address in a database connection, but unfortunately the hooks only work for database connection signups, not for social signups - so that wouldn’t be triggered when using sign up with Facebook.)
I had the same issue and wanted in my app the same control. An admin should first create a user in the database password connection. Then only users can login via social login.
The rule will prvent login in with a social account if their primary db account is not set up:
function disableSocialSignups(user, context, callback) {
// initialize app_metadata
user.app_metadata = user.app_metadata || {};
// Detect if this is the primary login/password connection
const isPrimaryDbConnection = context.connectionStrategy === 'auth0' &&
context.connection === 'Username-Password-Authentication';
// is this is a secondary login has it has not been allowed yet
if (!isPrimaryDbConnection && (user.app_metadata.secondaryLoginState !== 'ALLOWED')) {
// store the app_metadata
user.app_metadata.secondaryLoginState = 'PENDING';
auth0.users
.updateAppMetadata(user.user_id, user.app_metadata)
.then(() => {
console.log("Updated user app_metadata secondaryLoginState to " + user.app_metadata.secondaryLoginState);
var ManagementClient = require('auth0@2.27.0').ManagementClient;
var management = new ManagementClient({
token: auth0.accessToken,
domain: auth0.domain
});
console.log("Checking existence of user with same email");
return management.users.getByEmail(user.email);
})
.then(users => {
console.debug("Found users : " + users);
let allowSecondaryLogin = false;
for (let i in users) {
let existingUser = users[i];
if (existingUser.user_id !== user.user_id &&
existingUser.email_verified === true &&
existingUser.blocked !== false &&
existingUser.user_id.startsWith('auth0|')) {
allowSecondaryLogin = true;
break;
}
}
user.app_metadata.secondaryLoginState = allowSecondaryLogin ? 'ALLOWED' : 'DENIED';
return auth0.users.updateAppMetadata(user.user_id, user.app_metadata);
})
.then(() => {
let decision = user.app_metadata.secondaryLoginState;
console.log("Secondary login decision state for user : " + decision);
if (decision === 'ALLOWED') {
callback(null, user, context);
} else {
callback(new Error('Secondary login initialisation : ' + decision));
}
})
.catch(err => {
console.error("Failed to initialize secondary login for user " + user.email);
console.error(err);
callback(new Error('Failed to initialize secondary login'));
});
return;
}
return callback(null, user, context);
}