Prevent user creation (with hook?) if user is not whitelisted with rule

Hi all.

I’m trying to prevent user creation if user is not whitelisted with rules.

I have 2 rules in effect: domain whitelist & individual emails. I’m using social login (Google).

Rules work ok, users who’re not whitelisted are unable to login but accounts for them are still created in Auth0 dashboard & it doesn’t look very good.

By reading the docs & forum I was able to figure out that most probably I need to write a Pre-User Registration hook but I’m not sure exactly how it should be done.
Unfortunately I wasn’t able to find example like that in docs which is weird as this functionality seems like a core one to me.

Please assist me in writing the code for that hook. Or any other way to achieve my goal.
Maybe it can be added into docs by Auth0 team later?

Thanks.

Hi @vainkop,

That is correct about rules. By the time rules run, the user is already created in the system, so the rule would have to actually delete the user which would add complexity.

In a pre-registration hook, you could prevent the user from signing up like this:

module.exports = function (user, context, cb) {
  var response = {};
  const allowedList = [
    'user1@gmail.com',
    'user2@gmail.com'
  ];
  const isUserDenied = !allowedList.includes(user.email);

  if (isUserDenied) {
    return cb(new PreUserRegistrationError('Denied user registration in Pre-User Registration Hook'));
  }

  response.user = user;
  cb(null, response);
};

Note: the pre-user registration hook is available for database or passwordless connections only. This means that if you have a new user who signs up via Google or another social connection, the script will not run. If you need to cover all connections, then throwing an authorization error in rules would be the best option.

@stephanie.chamblee sorry but my question is explicitly talking about using the social login with Google so please tell me how can I prevent user creation in User Management → Users section of Auth0 if I’m using google-oauth2 to authenticate users?

If the use of rule which deletes user after creation is the only solution then it’s ok too even though it looks weird to allow user creation & then immediately delete him :slight_smile:

I’m also getting “[ESLint] ‘PreUserRegistrationError’ is not defined. (no-undef)” error with your code.

1 Like

Oh, I see the Google mention now! :upside_down_face:

Yes, only rules will cover all connections.

Usually, you’d just throw an authorization error like you’ve already mentioned. The user would be created, though. Here’s how you could delete the user:

  1. Create a M2M application:

  1. Authorize it to use the Managment API and allow it to use the delete:users scope:

  2. Add the M2M app’s client ID and client Secret as secret values to use in the rule:

  3. Create the rule (this is allowing certain domains, but you can adjust the userHasAccess criteria for emails):

async function emailDomainWhitelist(user, context, callback) {
  const axios = require('axios@0.19.2');

  const whitelist = ['example.com', 'example.org']; //authorized domains
  const userHasAccess = whitelist.some(
      function (domain) {
        const emailSplit = user.email.split('@');
        return emailSplit[emailSplit.length - 1].toLowerCase() === domain;
      }
  );

  if (userHasAccess) {
    return callback(null, user, context);
  }

  const options = {
    method: 'POST',
    url: `https://${auth0.domain}/oauth/token`,
    headers: {
      'content-type': 'application/json'
    },
    data: {
      "client_id": configuration.DELETE_USERS_CLIENT_ID,
      "client_secret": configuration.DELETE_USERS_CLIENT_SECRET,
      "audience": `https://${auth0.domain}/api/v2/`,
      "grant_type":"client_credentials"
    }
  };

  try {
    const tokenResponse = await axios(options);
    const accessToken = tokenResponse.data.access_token;
    const userId = encodeURIComponent(user.user_id);
    const deleteUserOptions = {
      method: 'DELETE',
      url: `https://${auth0.domain}/api/v2/users/${userId}`,
      headers: { Authorization: `Bearer ${accessToken}` }
    };
    await axios(deleteUserOptions);
    return callback(new UnauthorizedError('Access denied.'));
  } catch (err) {
    // handle error
    console.log(err);
    return callback(new UnauthorizedError('Access denied.'));
  }
}

@stephanie.chamblee Thank you for your answer I will try that!

But honestly that looks more like a development of the Auth0 platform itself & a workaround than just using it :slight_smile:
Auth0 is basically allowing to create users without authorization so theoretically if someone has a lot of social accounts he can ddos you with the registration requests & then with the workaround you’re suggesting M2M will ddos your api with delete requests.
I know that it’s not going to be easy to execute smth like that & there’s a limit of 10k for Google api too but still all of that doesn’t sound very good.

Imo that functionality is quite basic & should be covered with options selectable from UI & not just by deletion of created users but by preventing their creation in the fist place.

Unfortunately, there is not a simple way to prevent user creation with a social connection. The recommended approach is throwing an authorization error in a rule. The above approach is one way to implement what you need, but it is true that it is not simple.

It’d be great to have your use case in a feature request in our Feedback category:

I don’t think that it’s correct to determine that situation as just “not easy to implement”

That looks like a security hole in the platform which can be temporarily covered with a workaround but I’m not sure how can Auth0 pass a serious security audit with that.

If I was building a really serious authentication solution then I’d probably reevaluate other authentication solutions which do not that kind of problems in them.

Same for dynamic client registration Dynamic Client Registration

Note that Auth0 supports Open Dynamic Registration , which means that the endpoint will accept a registration request without an Access Token

Really?

1 Like

Also your workaround cannot be used by some clients & logins by external unauthorized google accounts can easily exhaust the number of api calls per month which is also a ddos:

This feature is included in your current plan up to 1,000 calls per month: upgrade your subscription to [Developer Pro] or [Enterprise] for over 1,000 monthly calls in production.

I’m using terraform to manage Auth0 & imo it’s not acceptable to limit the number of calls to your api like that. Putting a rate limit on it sound like a more fair option to me.

1 Like

Thanks for the feedback @vainkop! It’d be great to get this input in the feedback category so that this can be evaluated by the product team.

It looks like the Dynamic Client Registration feature is based on the open Dynamic Registration outlined in the OpenID Connect Dynamic Client Registration spec:

To support open Dynamic Registration, the Client Registration Endpoint SHOULD accept registration requests without OAuth 2.0 Access Tokens.

However, this feature may not fit your use case.

1 Like