Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure done callback is correctly fired on captcha reload #1469

Merged
merged 2 commits into from
Oct 17, 2024

Conversation

srijonsaha
Copy link
Contributor

@srijonsaha srijonsaha commented Oct 4, 2024

Changes

This change ensures that done callback is fired correctly after captcha is reloaded. This is especially necessary for Arkose since it relies on hooks to trigger the captcha puzzle. PR introduces a new global captchaReloaded variable and hoists the done callback to the global scope so it can changed by the reload function. The captchaReloaded will tell us if we need to call done callback again and now we can pass different done callbacks on initial load and reload.

NOTE: This does not address some of the other third party captchas and we'll need to make additional changes for reload mechanism to work with some of other third party captchas. Action item added: https://auth0team.atlassian.net/browse/IAMRISK-4199

References

https://auth0team.atlassian.net/browse/IAMRISK-4103
https://auth0team.atlassian.net/browse/ESD-41213

Testing

arkose-testing-on-reload.mov

Code used for testing: #1469 (comment)

  • This change adds unit test coverage
  • This change adds integration test coverage

Checklist

@srijonsaha srijonsaha requested a review from a team as a code owner October 4, 2024 17:48
@srijonsaha srijonsaha marked this pull request as draft October 4, 2024 17:48
@srijonsaha
Copy link
Contributor Author

This is the template code I used for the login page testing:

<!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%;
    }

    .login-box {
      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;
    }

    #error-message {
      display: none;
      white-space: break-spaces;
    }
  </style>
<body>
  <div class="login-container">
    <div class="col-xs-12 col-sm-4 col-sm-offset-4 login-box">
      <div class="login-header">
        <img src="https://cdn.auth0.com/styleguide/1.0.0/img/badge.svg"/>
        <h3>Welcome</h3>
        <h5>PLEASE LOG IN</h5>
      </div>
      <div id="error-message" class="alert alert-danger"></div>
      <form onsubmit="return false;" method="post">
        <div class="form-group">
         <label for="name">Email</label>
          <input
            type="email"
            class="form-control"
            id="email"
            placeholder="Enter your email">
        </div>
        <div class="form-group">
          <label for="name">Password</label>
          <input
            type="password"
            class="form-control"
            id="password"
            placeholder="Enter your password">
        </div>
        <div class="captcha-container form-group"></div>
        <button
          type="submit"
          id="btn-login"
          class="btn btn-primary btn-block">
            Log In
        </button>
        <button
          type="button"
          id="btn-reload"
          class="btn btn-default btn-block">
            Reload Captcha
        </button>
      </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="http://localhost:3000/auth0.js"></script>
  <script src="https://cdn.auth0.com/js/polyfills/1.0/object-assign.min.js"></script>
  <script>
    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 =  {
        overrides: {
          __tenant: config.auth0Tenant,
          __token_issuer: config.authorizationServer.issuer
        },
        domain: config.auth0Domain,
        clientID: config.clientID,
        redirectUri: config.callbackURL,
        responseType: 'code',
        scope: config.internalOptions.scope,
        _csrf: config.internalOptions._csrf,
        state: config.internalOptions.state,
        _intstate: config.internalOptions._intstate
      };

      var triggerCaptcha = null;
      var webAuth = new auth0.WebAuth(params);
      var databaseConnection = 'Username-Password-Authentication';
      var captcha = webAuth.renderCaptcha(
        document.querySelector('.captcha-container'),
        null,
        (error, payload) => {
          console.log("done callback after LOAD");
          if (payload) {
            triggerCaptcha = payload.triggerCaptcha;
            console.log("triggerCaptcha initialized after LOAD");
          }
        }
      );

      function login(e) {
        e.preventDefault();
        var button = document.getElementById('btn-login');
        var username = document.getElementById('email').value;
        var password = document.getElementById('password').value;
        var request = () => {
          webAuth.login({
            realm: databaseConnection,
            username: username,
            password: password,
            captcha: captcha.getValue()
          }, function(err) {
            if (err) displayError(err);
          });
        };
        if (triggerCaptcha) {
          triggerCaptcha(request);
        } else {
          request();
        }
      }

      function reload(e) {
        e.preventDefault();
        var button = document.getElementById('btn-reload');
        button.disabled = true;
        captcha.reload((error, payload) => {
          console.log("done callback after RELOAD");
          if (payload) {
            triggerCaptcha = payload.triggerCaptcha;
            console.log("triggerCaptcha initialized after RELOAD");
          }
          button.disabled = false;
        });
      }

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

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

@srijonsaha srijonsaha marked this pull request as ready for review October 11, 2024 23:24
@srijonsaha srijonsaha force-pushed the done-callback-on-reload-captcha branch from 49638f2 to 8d3c85e Compare October 17, 2024 19:37
@srijonsaha srijonsaha merged commit 26a8a89 into master Oct 17, 2024
15 checks passed
@srijonsaha srijonsaha deleted the done-callback-on-reload-captcha branch October 17, 2024 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants