pwshub.com

External User Verification with Forms

Some applications require a user to be verified by an external service before they can log in to the system. This can be in the form of an invite code for a free trial in a SaaS application, address verification for a real estate listing website, or maybe something more robust for a healthcare or financial services application.

Auth0 recently released Custom Prompts to help app builders collect more information about their users upon signup. These fields can be captured, and further processing can be done with the Pre Registration Action Flow. Capturing too much information (or capturing information conditionally) can have impacts on the end-user experience. Auth0 has recently released Forms, a new drag-and-drop editor for collecting user information, executing workflows, and orchestrating event data, which can be applied to these verification workflows as well. For this article, we will address the invite code workflow where users must verify their invitation code before being able to log in to the application.

Note: Custom Prompts and Forms work very nicely together as a user who completes a sign-up will then trigger a Login Flow where Forms can be launched.

In this blog post, we will leverage Auth0 Forms to collect this invite code and make an HTTP request to an externally hosted API to verify that the code + email combo is valid. This is one narrow use case, but the solution we are going to outline can handle any scenario where a user must provide input to be verified externally before granting access.

Use Case

Let’s imagine you have a SaaS application that has an upcoming private Beta launch. You do not want to restrict users from signing up to your platform (so you can ingest them into your MarTech stack), but you do not want to allow them to officially log in to the platform unless they have been given access by a member of your team or an affiliate. You could solve this use case in many ways, and in this instance, we will solve this by having users provide an “Invite Code” to verify they have been given access by your backend application. You would send the user’s email alongside this code before approving their access to your private launch. You could collect this code during the signup phase using Auth0 Custom Prompts, but if they failed the validation, their account would not be created. Your goal is to create the accounts and then only gate access to the private beta behind this invite code.

Prompting a User with a Form

We will use a Post-Login Action to launch a user into this flow. They will automatically enter this flow after sign up and any time they come back to your application. This Action will check a flag on the user's profile to see if they have been previously verified or not.

exports.onExecutePostLogin = async (event, api) => {
  if (event.user.app_metadata.verified !== true) {
     const FORM_ID = 'ap_eJWCKKPimBy86AyTRsQikQ';
     api.prompt.render(FORM_ID);
  }
};

You can access the Forms in your Auth0 tenant by navigating to ActionsForms, which will launch the editor in a new tab. Here is the visual editor for our specific Flow:

High-Level Form Flow

High Level Form Flow

The User is prompted to enter their invite code into a text prompt, and then a flow is invoked. In the image below, you can see the flow diagram that checks if the code result has an error, and if so, we will show an error message; otherwise, the flow continues.

Verification Flow Verification Flow

Here, we can see how to configure the HTTP request step to call your endpoint using the user’s email address and the collected invite code.

HTTP Request Structure HTTP Request Structure

Based on the response, if the result comes back as true, the user will continue the flow, and if not they will be shown an error message which will prevent them from continuing until they input a correct value.

Conditional Configuration Conditional Configuration

Once the user enters a correct value, the flow exits and returns to the main path, where it will let them know that access has been granted and they can continue using the application. Our Action that launched the flow must have a continue section to resume the authentication transaction, and we will also save a flag on their profile to prevent them from having to enter this flow again.

exports.onContinuePostLogin = async (event, api) => {
  api.user.setAppMetadata("verified", true);
};

Success Prompt Success Prompt

And here is the flow end-to-end for a new user who signs up and has a valid email + code combo.

End to End User Journey

Here is the finished JSON for you to begin building your verification flow today! You can import this directly into your tenant by navigating to the Forms window → Create Form → Import It!

Importing Existing Flow with JSON Importing Existing Flow with JSON

{
  "version": "3.0.0",
  "form": {
    "name": "Invite Code",
    "description": null,
    "messages": {
      "custom": {},
      "errors": {}
    },
    "languages": {
      "default": null,
      "primary": "en"
    },
    "translations": {},
    "start": {
      "nextNode": "step_Y3AO",
      "coordinates": {
        "x": 22,
        "y": 167
      },
      "hiddenFields": []
    },
    "nodes": [
      {
        "id": "step_Y3AO",
        "type": "STEP",
        "alias": "Collect Code",
        "config": {
          "nextNode": "flow_Cilk",
          "components": [
            {
              "id": "rich_text_sME2",
              "type": "RICH_TEXT",
              "config": {
                "content": "<h3><strong>Please enter your invite code.</strong></h3>"
              },
              "category": "BLOCK"
            },
            {
              "id": "invite_code",
              "hint": null,
              "type": "TEXT",
              "label": "Invite Code",
              "config": {
                "maxLength": null,
                "minLength": null,
                "multiline": false,
                "placeholder": "XXX-XXX",
                "defaultValue": null
              },
              "category": "FIELD",
              "required": true,
              "transient": false
            },
            {
              "id": "next_button_xlCe",
              "type": "NEXT_BUTTON",
              "config": {
                "text": "Continue"
              },
              "category": "BLOCK"
            }
          ]
        },
        "coordinates": {
          "x": 323,
          "y": -36
        }
      },
      {
        "id": "flow_Cilk",
        "type": "FLOW",
        "alias": "Verify Code",
        "config": {
          "flowId": "#FLOW-1#",
          "nextNode": "step_IifF"
        },
        "coordinates": {
          "x": 1051,
          "y": 139
        }
      },
      {
        "id": "step_IifF",
        "type": "STEP",
        "alias": "Verification Complete",
        "config": {
          "nextNode": "$ending",
          "components": [
            {
              "id": "rich_text_pMye",
              "type": "RICH_TEXT",
              "config": {
                "content": "<h3><strong>Welcome to Demo0, </strong></h3><h3><strong>Click Continue to get Started!</strong></h3>"
              },
              "category": "BLOCK"
            },
            {
              "id": "next_button_Z6Md",
              "type": "NEXT_BUTTON",
              "config": {
                "text": "Continue"
              },
              "category": "BLOCK"
            }
          ]
        },
        "coordinates": {
          "x": 1510,
          "y": -2
        }
      }
    ],
    "ending": {
      "content": null,
      "redirection": null,
      "callback": null,
      "afterSubmit": {
        "email": null,
        "flowId": null
      },
      "coordinates": {
        "x": 2194,
        "y": 110
      },
      "resumeFlow": true
    },
    "social": [],
    "style": {
      "css": null,
      "theme": "ROUND",
      "version": "MODERN"
    },
    "tags": []
  },
  "flows": {
    "#FLOW-1#": {
      "name": "Verify Invite Code",
      "description": null,
      "actions": [
        {
          "id": "http_request_verify_code",
          "type": "HTTP",
          "alias": "Verify Invite Code",
          "notes": null,
          "action": "SEND_REQUEST",
          "params": {
            "url": "https://edge.samyap.dev/api/verify-code",
            "body": {
              "email": "{{context.user.email}}",
              "invite_code": "{{fields.invite_code}}"
            },
            "type": "JSON",
            "basic": null,
            "method": "POST",
            "params": {},
            "headers": {},
            "acceptNOK": false,
            "connectionId": null
          },
          "allowFailure": false
        },
        {
          "id": "if_then_condition_q0Ym",
          "type": "FLOW",
          "alias": "Verify Code Result",
          "notes": null,
          "action": "BOOLEAN_CONDITION",
          "params": {
            "then": [],
            "evaluate": {
              "operands": [
                {
                  "operands": [
                    "{{ http_request_verify_code.body.result }}",
                    "true"
                  ],
                  "operator": "EQ"
                }
              ],
              "operator": "AND"
            },
            "otherwise": [
              {
                "id": "show_error_message_4rkM",
                "type": "FLOW",
                "alias": null,
                "notes": null,
                "action": "ERROR_MESSAGE",
                "params": {
                  "message": "Your code is invalid.  Please contact support for help"
                },
                "allowFailure": false
              }
            ]
          },
          "allowFailure": false
        }
      ],
      "triggers": {
        "webhook": {
          "secret": null,
          "enabled": false
        }
      },
      "synchronous": true,
      "security": {
        "rateLimits": []
      }
    }
  },
  "connections": {}
}

Conclusion

Today you learned how to leverage Auth0 Forms to gather input from users to verify them with external systems using the no-code Forms and Flows editors. This capability can be extended to numerous applications such as Progressive Profiling, Consent Collection and many more.

At Auth0, we aim to provide a high-quality service and developer experience for our customers. The first interaction with your customers is oftentimes a login screen, so we understand how important it is for the user experience to be top-notch. With our hosted Universal Login, we take away the burden of deploying and maintaining these highly secure workflows. With the capabilities of our forms outlined in this post, we are able to help your teams iterate more quickly and customize the experience to be sticky for your brand and ultimately help your business grow.

Source: auth0.com

Related stories
3 weeks ago - Email marketing is the process of nurturing relationships with potential and existing customers through email. It’s a powerful tool that can boost your sales, enhance brand loyalty, and drive business growth. Leveraging the right email...
1 month ago - In this in-depth guide, I’ll be showing how to secure a Next.js AI app deployed on Vercel. We’ll be taking a hands-on approach by starting with a simple AI app riddled with vulnerabilities. This article will guide you through how you can...
1 week ago - No-code platforms are tools that help people with little to no coding knowledge build applications, websites, and more with their drag-and-drop interface and customizable code templates. These tools offer pre-built components, AI...
1 month ago - Bright Data is a well-known proxy provider that offers extensive tools and products to users looking for data scraping solutions and proxy services. Here are some of Bright Data’s most popular offerings: In this review, we will examine...
1 month ago - Synthetic monitoring simulates user interactions with a website or web system to proactively identify performance issues and ensure functionality before impacting real users. It uses automated scripts to test and monitor system behavior...
Other stories
1 hour ago - Ubuntu 24.10 ‘Oracular Oriole’ is released on October 13th, and as you’d expect from a new version of Ubuntu, it’s packed with new features. As a short-term release, Ubuntu 24.10 gets 9 months of ongoing updates, security patches, and...
3 hours ago - Did you know that CSS can play a significant role in web accessibility? While CSS primarily handles the visual presentation of a webpage, when you use it properly it can enhance the user’s experience and improve accessibility. In this...
4 hours ago - Design thinking workshops are your key to turning big problems into clear solutions. In this blog, I share how to run them efficiently and keep your team aligned. The post How to run a design thinking workshop appeared first on LogRocket...
4 hours ago - New memory-optimized X8g instances offer up to 3 TiB DDR5 memory, 192 vCPUs, and 50 Gbps network bandwidth, designed for memory-intensive workloads like databases, analytics, and caching with unparalleled price/performance and efficiency.
4 hours ago - Gain indispensable data engineering expertise through a hands-on specialization by DeepLearning.AI and AWS. This professional certificate covers ingestion, storage, querying, modeling, and more.