How to implement Invitation Only registration and set password process

I am trying to follow the Invite Only Aplication article here https://auth0.com/docs/design/creating-invite-only-applications, but it seems like this article is missing some important information on setting up this flow.

If I configure a callback on my Verification Email template, then after the user verifies their email, they will be redirected back to my app with a URL that looks like http://localhost:8080/?supportSignUp=true&supportForgotPassword=true&email=johndoe%40test.com&message=Your%20email%20was%20verified.%20You%20can%20continue%20using%20the%20application.&success=true#

However, they are not authenticated at this point are they? I could parse this URL and generate a PW reset ticket via my backend for the email specified in the email parameter but this seems unsecure. I can’t blindly redirect to a password reset page for john doe, otherwise anyone would be able to put that URL in and reset his password…

Please advise on the steps between getting a verified user and generating a password reset ticket.

1 Like

FWIW, this is what I think I’m going to do. I am using auth0 as my identity store.

  1. Send a post from my backend to create a new auth0 user. At this point the auth0 user.email_verified = false.
  2. Send a post to trigger a password reset email for the new user.

I customized the password reset email template with an if statement to disguise it as an invitation when user.email_verified = false

{% if user.email_verified == false %}
            <h1>Invitation to our awesome app</h1>

            <p>Please verify your email address and set your initial password by clicking the following link:</p>

            <p><a href="{{ url }}">Confirm my account</a></p>

  {% else %}

            <h1>Password Change Request</h1>

            <p>You have submitted a password change request. </p>

            <p>If it wasn't you please disregard this email and make sure you can still login to your account. If it was you, then to <strong>confirm the password change <a href="{{ url }}">click here</a></strong>.</p>

    {% endif %}

            <p>If you have any issues with your account, please don’t hesitate to contact us at 1-888-AWESOMECO.</p>

            <br>
            Thanks!
            <br>
  1. Configure a redirect on the Password Reset email template so that when the user clicks the invitation link, they will be prompted to reset their password and then they will be redirected to our app, which will then ask them to login
  2. I added an auth0 Rule to set email_verified = true on first login/password reset ( it was one of the canned options)
function (user, context, callback) {
  const request = require('request');
  const userApiUrl = auth0.baseUrl + '/users/';

  // This rule is only for Auth0 databases
  if (context.connectionStrategy !== 'auth0') {
    return callback(null, user, context);
  }

  if (user.email_verified || !user.last_password_reset) {
    return callback(null, user, context);
  }

  // Set email verified if a user has already updated his/her password
  request.patch({
    url: userApiUrl + user.user_id,
    headers: {
      Authorization: 'Bearer ' + auth0.accessToken
    },
    json: { email_verified: true },
    timeout: 5000
  },
  function(err, response, body) {
    // Setting email verified isn't propagated to id_token in this
    // authentication cycle so explicitly set it to true given no errors.
    context.idToken.email_verified = (!err && response.statusCode === 200);

    // Return with success at this point.
    return callback(null, user, context);
  });
}
  1. Next time we need to send them a password reset email it will use the “existing user” flavor of the template
  2. The invitation email pw reset link has a configurable TTL – it defaults to 5 days. So if they don’t accept the invite it will eventually timeout (and we could send them another one if needed)
9 Likes

Nice workaround, though it’s sad they don’t support a solution like this out of the gate.

3 Likes

Thank you everyone! Definitely the solution caught my attention. Will make sure to relay that as feedback to appropriate team!

1 Like

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.