Count down retry Resend OTP in Passwordless using Universal Login

Currently, we are using feature Passwordless with Universal Login to authenticate user,
We also enable button to user Resend OTP to email into form login
But, user can press button quickly.

So, my question is: How to disable button after he click, and wait few second to enable it again (5 seconds is fine)!
Better, Ciould I add a clock count down to do that
Thank for your answer

I built a solution based on customizing the Universal Login Page, so it will work only with the New Universal Login experience. With modifications, it ‘may’ work with Classic Universal Login also.

Pre-requisites:

  • A Custom Domain is a prerequisite for using New Universal Login Page Templates.
  • In the Dashboard > Branding, the Email Provider and/or Phone Provider have been setup and unit tested.
  • In the Dashboard, menu Authentication > Passwordless. the respective flow has been configured and it is verified that SMS/Email is being sent during unit test.
  • The App being test has the Email/SMS Passwordless connection toggle enabled (green)
  • In the Dashboard, expand the menu as follows: Authentication > Authentication Profile and set the profile to Identifier First.
  • Load your Test App’s Home Page and click Login to start testing.

Code Snippet:

  {% if prompt.name == "login-passwordless" and prompt.screen.name == "login-passwordless-email-code" %}
  <script>
      // DEBUG FLAG - turn this off in UAT and Prod.
      const debug = "Y" === "Y" ? true : false;
      function debugLog(message) {
        // If the debug flag is true, log the message
        if (debug) {
          // Get current timestamp
          const timestamp = new Date().toISOString();
          // Log the message with timestamp to the console 
          console.log(`${timestamp} ${message}`);
          //console.log(`${message}`);
        }
      }
      // ADD YOUR OWN CUSTOM DOMAIN HERE
      // Auth0 Domain and flow invoking App Details
      const auth0_domain    = "<YOUR_CUSTOM_DOMAIN>";
      const appName         = "{{application.name}}";
      // Name of the Universal Login Prompt and Screen being rendered.
      const promptName      = "{{prompt.name}}";
      const prompScreenName = "{{prompt.screen.name}}";
      debugLog("promptName      = " + promptName);
      debugLog("prompScreenName = " + prompScreenName);
      debugLog("appName         = " + appName );
      // Add an onLoad event listener to fire the number of submits function.
      window.addEventListener("load", checkResendSubmit);
      function checkResendSubmit() {
        var action  = GetURLParameter("action");
        debugLog("action = "+action);
        if(action === undefined) {
          // Resend not yet clicked so this is first load of same page.
          debugLog("Resend NOT clicked yet. First Page Load.");
        } else {
          // Resend was clicked at least once.
          debugLog("Resend clicked.");
        }
        debugLog("document.forms[1].action = "+document.forms[1].action);
        var newUrl = auth0_domain + "/u/login/passwordless-email-challenge" + "?action=resend";
        document.forms[1].action = newUrl;
        // Now manipulate the Resend button for 30 seconds if it was already clicked previously.
        if(action === "resend") {
          // Start non-blocking timer
          var duration = 30;
            // Disable the 'Resend' button
            document.forms[1].elements.action.setAttribute("disabled", "true");
            var timer = duration, minutes, seconds;
            setInterval(function () {
                minutes = parseInt(timer / 60, 10);
                seconds = parseInt(timer % 60, 10);
                minutes = minutes < 10 ? "0" + minutes : minutes;
                seconds = seconds < 10 ? "0" + seconds : seconds;
                document.forms[1].elements.action.setAttribute("style", "color:gray");
                document.forms[1].elements.action.innerText = "Resend OTP after "+ seconds +" seconds";
                debugLog("timer : "+timer);
                if (--timer < 1) {
                    document.forms[1].elements.action.innerText = "Resend";
                    document.forms[1].elements.action.style = "";
                    document.forms[1].elements.action.disabled = false;
                    return;
                }
            }, 1000);
            // Enable the Resend button again
            document.forms[1].elements.action.setAttribute("disabled", "false");
        }
      }
      function GetURLParameter(sParam) {
        var sPageURL = window.location.search.substring(1);
        var sURLVariables = sPageURL.split("&");
        for (var i = 0; i < sURLVariables.length; i++) {
          var sParameterName = sURLVariables[i].split("=");
          if(sParameterName[0] == sParam) {
            return sParameterName[1];
          }
        }
      }
    </script>
  {% endif %}

Code Snippet Usage Instructions

  • The Universal Login Page Template can be set via the Management API or loaded into an IDE/Editor using the. I personally find the Auth0 CLI more developer-friendly as the Login Page Template can be customized using an IDE of choice like VS Code or Xcode.
  • The Code Snippet above has to be injected somewhere in between the<head> and </head> tags. At the end of the day, the code snippet is JavaScript code between <script> and </script> tags.
  • However, it should be injected in the HTML header because, it will register an Event Handler on the Window to determine if the ‘Resend’ button/link was clicked or not.
  • In the snippet, at line 20, you have to specify the Custom Domain of your tenant as value of the variable auth0_domain. In a CI/CD pipeline, this value can be passed using config parameters e.g. AWS Secrets in a Terraform deployment script.
  • To set your own Timer interval (in seconds), change the value of the duration variable at line 58 in the snippet.

Risks:

  • The solution is primarily reliant upon JavaScript and is dependent on JavaScript support in browsers.
  • There is no error handling in this code.
  • The code has JavaScript DOM manipulation involved and Auth0 Product Engineering may change the DOM structure of the Auth0 Widget without notice. This can break critically break the functionality of this solution.
  • It also makes use of the passwordless endpoint <YOUR_Auth0_Domain>/u/login/passwordless-email-challenge.

Hi everyone!

Thank you @auziro for sharing your custom solution to the issue!

Kind Regards,
Nik