How to use Passwordless, Database and Social connections in the same classic universal login page

Problem Statement

We would like to use the Classic UL and have the following connections available for a user to choose from:

  • Passwordless
  • Database
  • Social

Solution

Here is a sample solution written with Auth0.js to render a login widget that provides a link to allow members to log in with a passwordless connection as well.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Sign In with Auth0</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
  <style>
    body, html {
      height: 100%;
      background-color: #f9f9f9;
    }

    .login-container {
      position: relative;
      height: 100%;
      background-color: #FFFEF4;
    }
    
    #login-modal-box {
      background-color: #ebebeb;
    }

    .login-box {
      width: 320px;
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      padding: 15px;
      background-color: #fff;
      box-shadow: 0px 5px 5px #ccc;
      border-radius: 5px;
      border-top: 1px solid #e9e9e9;
    }

    .login-header {
      text-align: center;
    }

    .login-header img {
      width: 75px;
    }
    
    #btn-login {
      cursor: pointer;
      width: 100%;
      height: 35px;
      display: flex;
      justify-content: center;
      align-items: center;
      border-radius: 5px;
      background-color: #02112A;
      color: #FFFEF4;
    }
    
    #btn-login:hover {
      background-color: #80878F;
      color: #02112A;
    }
    
    #btn-signup {
      display: none;
      cursor: pointer;
      width: 100%;
      height: 35px;
      display: flex;
      justify-content: center;
      align-items: center;
      border-radius: 5px;
      background-color: #FFFEF4;
      border: 1px solid #02112A;
      color: #02112A;
    }
    
    #btn-signup:hover {
      background-color: #80878F;
      border: 1px solid #80878F;
      color: #02112A;
    }
    
    #btn-google {
      cursor: pointer;
      width: 100%;
      height: 35px;
      display: none;
      justify-content: center;
      align-items: center;
      border-radius: 5px;
      background-color: #39D435;
      color: #02112A;
    }
    
    #btn-google:hover {
      background-color: #80878F;
      color: #02112A;
    }

    #error-message {
      display: none;
      white-space: break-spaces;
    }
    
    #switch_login_type_btn_div {
      width: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    #passwordless_info_text {
      display: block;
      color: #02112A;
    }
    
    #switch_to_passwordless_btn {
      display: none;
      cursor: pointer;
      color: #02112A;
    }
    
    #switch_to_passwordless_btn:hover {
      color: #C3C1A8;
    }
    
    #switch_to_usernamepassword_btn {
      display: block;
      cursor: pointer;
      color: #02112A;
    }
    
    #switch_to_usernamepassword_btn:hover {
      color: #C3C1A8;
    }
    
    #password_input_div {
      display: none;
    }
    
    #code_input_div {
      display: none;
    }
  </style>
<body>
  <div class="login-container">
    <div id="login-modal-box" class="col-xs-12 col-sm-4 col-sm-offset-4 login-box">
      <div class="login-header">
        <img src="https://fartheradvisorphotos.s3.amazonaws.com/farther_favicon.png"/>
        <h3>Welcome</h3>
        <h5>Log In To Farther</h5>
      </div>
      
      <div id="switch_login_type_btn_div">
        <p id="switch_to_passwordless_btn" onclick="switchToPasswordless()">
          Switch to Passwordless ->
        </p>

        <p id="switch_to_usernamepassword_btn" onclick="switchToUsernamePassword()">
          Switch to Username + Password ->
        </p>
      </div>
      
      <div id="error-message" class="alert alert-danger"></div>
      <form onsubmit="return false;" method="post">
        <div id="email_input_div" class="form-group">
         <label for="name">Email</label>
          <input
            type="email"
            class="form-control"
            id="email"
            placeholder="Enter your email">
        </div>
        <div id="password_input_div" class="form-group">
          <label for="name">Password</label>
          <input
            type="password"
            class="form-control"
            id="password"
            placeholder="Enter your password">
        </div>
        <div id="code_input_div" class="form-group">
          <label for="name">Code</label>
          <input
            type="text"
            class="form-control"
            id="code"
            placeholder="Enter your code">
        </div>
        <p id="passwordless_info_text">
          We will send a link to this email
        </p>
        <div class="captcha-container form-group"></div>
        <p
          type="button"
          id="btn-login">
            Log In
        </p>
        <p
          type="button"
          id="btn-signup">
            Sign Up
        </p>
        <hr>
        <p
          type="button"
          id="btn-google">
            Log In with Google
        </p>
      </form>
    </div>
  </div>

  <!--[if IE 8]>
  <script src="//cdnjs.cloudflare.com/ajax/libs/ie8/0.2.5/ie8.js"></script>
  <![endif]-->

  <!--[if lte IE 9]>
  <script src="https://cdn.auth0.com/js/polyfills/1.0/base64.min.js"></script>
  <script src="https://cdn.auth0.com/js/polyfills/1.0/es5-shim.min.js"></script>
  <![endif]-->

  <script src="https://cdn.auth0.com/js/auth0/9.18/auth0.min.js"></script>
  <script src="https://cdn.auth0.com/js/polyfills/1.0/object-assign.min.js"></script>
  <script>
    let auth_type_is_passwordless = true;
    let isLoading = false;
    let email_used = '';
    let to_submit_code = false;
    
    function switchToPasswordless() {
      document.getElementById("switch_to_passwordless_btn").style.display = "none";
      document.getElementById("switch_to_usernamepassword_btn").style.display = "block";
      document.getElementById("password_input_div").style.display = "none";
      document.getElementById("passwordless_info_text").style.display = "block";
      document.getElementById("btn-google").style.display = "none";
      auth_type_is_passwordless = true;
    }
      
    function switchToUsernamePassword() {
      document.getElementById("switch_to_passwordless_btn").style.display = "block";
      document.getElementById("switch_to_usernamepassword_btn").style.display = "none";
      document.getElementById("password_input_div").style.display = "block";
      document.getElementById("passwordless_info_text").style.display = "none";
      document.getElementById("passwordless_info_text").innerHTML = "We will send a link to this email";
      document.getElementById("btn-google").style.display = "flex";
      auth_type_is_passwordless = false;
      to_submit_code = false;
      document.getElementById("email_input_div").style.display = "block";
      document.getElementById("code_input_div").style.display = "none";
    }
    
    window.addEventListener('load', function() {

      var config = JSON.parse(
        decodeURIComponent(escape(window.atob('@@config@@')))
      );

      var leeway = config.internalOptions.leeway;
      if (leeway) {
        var convertedLeeway = parseInt(leeway);
      
        if (!isNaN(convertedLeeway)) {
          config.internalOptions.leeway = convertedLeeway;
        }
      }

      var params = Object.assign({
        overrides: {
          __tenant: config.auth0Tenant,
          __token_issuer: config.authorizationServer.issuer
        },
        domain: config.auth0Domain,
        clientID: config.clientID,
        redirectUri: config.callbackURL,
        responseType: 'code'
      }, config.internalOptions);

      var webAuth = new auth0.WebAuth(params);
      var databaseConnection = 'Username-Password-Authentication';
      var captcha = webAuth.renderCaptcha(
        document.querySelector('.captcha-container')
      );
      
      function login() {
        if (!isLoading) {
          isLoading = true;
          if (to_submit_code) {
            submitPasswordlessCode()
          } else {
            if (auth_type_is_passwordless) {
              login_Passwordless();
            } else {
              login_UsernamePassword();
            }
          }
        }
      }
      
      // Passwordless  \/
      
      var webAuth_passwordless = new auth0.WebAuth({
        clientID: config.clientID,
        domain: config.auth0Domain,
        redirectUri: config.callbackURL,
        responseType: 'token id_token'
      });
      
      function login_Passwordless() {
        var email = document.getElementById('email').value;
        
        // set cookie
        let d = new Date();
        d.setTime(d.getTime() + (1*60*1000*525600));
        let expires = "expires=" + d.toUTCString();
        document.cookie = "auth0_email=" + email + ";" + expires + ";path=/;samesite=strict";
        
        webAuth_passwordless.passwordlessStart({
            connection: 'email',
            send: 'link', //code
            email: email
          }, function (err, res) {
            isLoading = false;
            if (err) displayError(err);
          
            if (err) {
              console.log(err);
              document.getElementById("passwordless_info_text").innerHTML = "Apologies, there was an error. Please try again";
            } else {
              /*
              to_submit_code = true;
              document.getElementById("passwordless_info_text").innerHTML = "Code sent! Please check your email";
              document.getElementById("email_input_div").style.display = "none";
              document.getElementById("code_input_div").style.display = "block";
              email_used = email;
              */
              console.log(res);
              document.getElementById("passwordless_info_text").innerHTML = "Link sent! Please check your email";
            }
          }
        );
      }
      
      function submitPasswordlessCode() {
        var code = document.getElementById('code').value;
        webAuth.passwordlessLogin({
          connection: 'email',
          email: email_used,
          verificationCode: code
        }, function (err, res) {
          isLoading = false;
          if (err) {
            document.getElementById("passwordless_info_text").innerHTML = "Error or wrong code. Please try again";
          } else {
            console.log(res);
          }
        });
      }
      
      // Passwordless  /\
      

      function login_UsernamePassword() {
        //e.preventDefault();
        //var button = this;
        var email = document.getElementById('email').value;
        var password = document.getElementById('password').value;
        //button.disabled = true;
        
        // set cookie
        let d = new Date();
        d.setTime(d.getTime() + (1*60*1000*525600));
        let expires = "expires=" + d.toUTCString();
        document.cookie = "auth0_email=" + email + ";" + expires + ";path=/;samesite=strict";
        
        webAuth.login({
          realm: databaseConnection,
          username: email,
          password: password,
          captcha: captcha.getValue()
        }, function(err) {
          isLoading = false;
          if (err) displayError(err);
          //button.disabled = false;
        });
      }

      function signup() {
        if (!isLoading) {
          isLoading = true;
          //var button = this;
          var email = document.getElementById('email').value;
          var password = document.getElementById('password').value;

          // set cookie
          let d = new Date();
          d.setTime(d.getTime() + (1*60*1000*525600));
          let expires = "expires=" + d.toUTCString();
          document.cookie = "auth0_email=" + email + ";" + expires + ";path=/;samesite=strict";

          //button.disabled = true;
          webAuth.redirect.signupAndLogin({
            connection: databaseConnection,
            email: email,
            password: password,
            captcha: captcha.getValue()
          }, function(err) {
            isLoading = false;
            if (err) displayError(err);
            //button.disabled = false;
          });
        }
      }

      function loginWithGoogle() {
        if (!isLoading) {
          isLoading = true;
          webAuth.authorize({
            connection: 'google-oauth2'
          }, function(err) {
            isLoading = false;
            if (err) displayError(err);
          });
        }
      }

      function displayError(err) {
        captcha.reload();
        var errorMessage = document.getElementById('error-message');
        errorMessage.innerHTML = err.policy || err.description;
        errorMessage.style.display = 'block';
      }

      document.getElementById('btn-login').addEventListener('click', login);
      document.getElementById('btn-google').addEventListener('click', loginWithGoogle);
      document.getElementById('btn-signup').addEventListener('click', signup);
    });
  </script>
</body>
</html>