Only Allow a Set List of Users to Sign-up

Overview

This article provides instructions for configuring the user sign-up process to only allow users whose usernames exist in an external database. This guide also explains how to hide the default sign-up link from the login page and create a unique, shareable link for user registration.

Applies To

  • Actions
  • External Databases
  • Sign-up Flow
  • Customize Universal Login Page Templates

Solution

  1. Hide the default sign-up link by customizing the Universal Login Page Template. For more information, see Customizing Universal Login Page Templates.

    • NOTE: A custom domain must be configured for the tenant before using Page Templates.
    • Use the following sample code as a reference to modify the template. This code hides the sign-up link by setting the display style of ulp-alternate-action to none. The _widget-auto-layout class centers the prompt on the page.
<!DOCTYPE html>
<html>
  <head>
    {%- auth0:head -%}
    <style>
      .ulp-alternate-action {
        display: none !important;
      }
    </style>
  </head>
  <body class="_widget-auto-layout">
    {%- auth0:widget -%}
  </body>
</html>
  1. Create a shareable sign-up link by adding a new route for sign-up in the application. The following example uses Express.js.
router.get("/signup", (req, res) => {
  res.oidc.login({
    returnTo: "/",
    authorizationParams: { screen_hint: "signup" },
  });
});
  • In this example, the screen_hint parameter in the /authorize call is set to signup. This redirects the user to the sign-up page, creating a dynamic state. This behavior is identical to following the link that is now hidden on the login page. When a user navigates to www.<domain>.com/signup, they are redirected to a sign-up page.
  1. Create a Pre-User Registration Action to allow only users whose usernames exist in an external database. This action checks an external database for a list of usernames before completing the sign-up. The following example uses Supabase as the external database.
exports.onExecutePreUserRegistration = async (event, api) => {
  const { createClient } = require("@supabase/supabase-js");

  const SUPABASE_URL = event.secrets.SUPABASE_URL;
  const SUPABASE_KEY = event.secrets.SUPABASE_KEY;

  const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);

  // Get the username for the user that's trying to sign up
  const username = event.user.username;

  // Query 'users' table for a matching username
  const { data, error } = await supabase
    .from("users")
    .select("*")
    .or(`username.eq.${username}`);

  // If there are any errors connecting to Supabase, deny registration
  if (error) {
    api.access.deny("Supabase error", error.message);
  }

  // If no matching usernames are found, deny registration
  if (data && data.length == 0) {
    api.access.deny("denied", "Access Denied");
  }
};
  • When a user attempts to sign up, this action checks if the username exists in the database. If there are any errors connecting to Supabase or if the user does not exist in the database, access is denied, and the user is not created in Auth0. Otherwise, the sign-up flow continues as expected.

NOTE: The sample code provided is for example purposes. Further customization depends on specific requirements or use cases.