Auth0 Home Blog Docs

Advice on proper approach


#1

We need to collect additional user data during the registration process (for social and email).

Some sources I’ve read suggest we should create a rule to redirect back to our site to our own form.

However, I tried this and it seems rules can’t distinguish between registration vs login. The redirect rule ignores context.stats.loginCount === 1 so the rule always fires. Perhaps I’m implementing the rule wrong?

I found another source suggesting adding a preregistration hook and adding metadata to the user.

But this suggests storing the users data on Auth0, not on my own database, which feels inappropriate.

Basically, we need to associate data with users such as address, stripe_id, opt in/out of news letter, history of what events they’ve registered for, etc. which should clearly be managed by our database, not Auth0.

Combing the docs and the community I have yet to find a clear answer as to the proper approach to accomplish this. Can someone kindly nudge me in the right direction? Thanks in advance for your advice.


#2

HI!

From the server perspective, registration and authentication are two different things. “Registration” is something that only happens really for database connections. A registration can happen by:

  • using either the “Sign up” page in Lock or the signup() method in Auth0.js, both of which use the public "/dbconnections/signup` endpoint (docs).
  • using the Management API v2 create user endpoint (POST /api/v2/users). This endpoint is protected, and can only be used from a server application that has credentials to access the Management API.

The pre and post user registration hooks only run on user registration and they don’t allow redirects.

There’s no such thing, from the server perspective, as a “registration” for social logins (or any other login where Auth0 delegates authentication to an external identity provider).

Rules only run after authentication, not during registration. But there’s an implicit authentication on most cases after the user registration (Lock does it, as does Auth0.js).

If you want to collect additional data from your users, the first design decisions (and something that the docs sometimes skip or take for granted) are who will be in charge of collecting that information and, like you said, where you will store that information.

  • Is this information related to authentication in general, can multiple applications benefit from that? If that’s the case, then Auth0 should probably ensure that the information is collected before sending the response to the application. It probably also makes sense to store that information in a centralized place (the Auth0 user profile).
  • Is the information specific to a single application? Then it might be a better idea to collect that information directly in the application after you get the authentication response from Auth0, and store that information in the application (using Auth0’s user_id/sub claim to correlate to the identity that logged in). You can even do this in a progressive way to avoid scaring users away (i.e. ask for the info on successive logins, or when the information is really required).

If you decide that Auth0 should ensure that the information is collected before going back to the application with an authentication response, then redirect rules are a good choice. You can use context.stats.loginCount, context.protocol (to know the rule is running on a regular token request, on a redirect callback, on a refresh token exchange, on a silent token request, and so on). But if the additional information required is mandatory, then a simpler logic might apply:

function(user, context, callback) {
  // you can use context.clientID 
  // to skip the rule for certain applications
  // [...]


  // this function will have your own logic to decide if the profile is filled out
  // you can check an external DB or the user profile
  // depending on where you chose to store the information
  function isUserProfileCompleted(user, cb) {
    [...]
  }

  isUserProfileCompleted(user, function(err, completed) {
    if (err) {
      return callback(err);
    }
    if (!completed) {
      // user profile is not completed
      // need to redirect
      context.redirect = {
        url = "https://mysystem.com/complete-user-profile";
      };
    }
    callback(null, user, context);
  });
}