[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/media/plg_multifactorauth_webauthn/js/ -> webauthn.js (source)

   1  /**
   2   * @package     Joomla.Plugin
   3   * @subpackage  Multifactorauth.webauthn
   4   *
   5   * @copyright   (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
   6   * @license     GNU General Public License version 2 or later; see LICENSE.txt
   7   */
   8  ((Joomla, document) => {
   9  
  10    let authData = null;
  11  
  12    const arrayToBase64String = a => btoa(String.fromCharCode(...a));
  13  
  14    const base64url2base64 = input => {
  15      let output = input.replace(/-/g, '+').replace(/_/g, '/');
  16      const pad = output.length % 4;
  17  
  18      if (pad) {
  19        if (pad === 1) {
  20          throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding');
  21        }
  22  
  23        output += new Array(5 - pad).join('=');
  24      }
  25  
  26      return output;
  27    };
  28  
  29    const displayError = message => {
  30      try {
  31        Joomla.renderMessages({
  32          error: message
  33        });
  34      } catch (e) {
  35        alert(message);
  36      }
  37    };
  38  
  39    const handleError = message => {
  40      try {
  41        document.getElementById('plg_multifactorauth_webauthn_validate_button').style.disabled = 'null';
  42      } catch (e) {// Do nothing
  43      }
  44  
  45      displayError(message);
  46    };
  47  
  48    const setUp = e => {
  49      e.preventDefault(); // Make sure the browser supports Webauthn
  50  
  51      if (!('credentials' in navigator)) {
  52        displayError(Joomla.Text._('PLG_MULTIFACTORAUTH_WEBAUTHN_ERR_NOTAVAILABLE_HEAD'));
  53        return false;
  54      }
  55  
  56      const rawPKData = document.forms['com-users-method-edit'].querySelectorAll('input[name="pkRequest"]')[0].value;
  57      const publicKey = JSON.parse(atob(rawPKData)); // Convert the public key information to a format usable by the browser's credentials manager
  58  
  59      publicKey.challenge = Uint8Array.from(window.atob(base64url2base64(publicKey.challenge)), c => c.charCodeAt(0));
  60      publicKey.user.id = Uint8Array.from(window.atob(publicKey.user.id), c => c.charCodeAt(0));
  61  
  62      if (publicKey.excludeCredentials) {
  63        publicKey.excludeCredentials = publicKey.excludeCredentials.map(data => {
  64          data.id = Uint8Array.from(window.atob(base64url2base64(data.id)), c => c.charCodeAt(0));
  65          return data;
  66        });
  67      } // Ask the browser to prompt the user for their authenticator
  68  
  69  
  70      navigator.credentials.create({
  71        publicKey
  72      }).then(data => {
  73        const publicKeyCredential = {
  74          id: data.id,
  75          type: data.type,
  76          rawId: arrayToBase64String(new Uint8Array(data.rawId)),
  77          response: {
  78            clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)),
  79            attestationObject: arrayToBase64String(new Uint8Array(data.response.attestationObject))
  80          }
  81        }; // Store the WebAuthn reply
  82  
  83        document.getElementById('com-users-method-code').value = btoa(JSON.stringify(publicKeyCredential)); // Submit the form
  84  
  85        document.forms['com-users-method-edit'].submit();
  86      }, error => {
  87        // An error occurred: timeout, request to provide the authenticator refused, hardware / software
  88        // error...
  89        handleError(error);
  90      });
  91      return false;
  92    };
  93  
  94    const validate = () => {
  95      // Make sure the browser supports Webauthn
  96      if (!('credentials' in navigator)) {
  97        displayError(Joomla.Text._('PLG_MULTIFACTORAUTH_WEBAUTHN_ERR_NOTAVAILABLE_HEAD'));
  98        return;
  99      }
 100  
 101      const publicKey = authData;
 102  
 103      if (!publicKey.challenge) {
 104        handleError(Joomla.Text._('PLG_MULTIFACTORAUTH_WEBAUTHN_ERR_NO_STORED_CREDENTIAL'));
 105        return;
 106      }
 107  
 108      publicKey.challenge = Uint8Array.from(window.atob(base64url2base64(publicKey.challenge)), c => c.charCodeAt(0));
 109  
 110      if (publicKey.allowCredentials) {
 111        publicKey.allowCredentials = publicKey.allowCredentials.map(data => {
 112          data.id = Uint8Array.from(window.atob(base64url2base64(data.id)), c => c.charCodeAt(0));
 113          return data;
 114        });
 115      }
 116  
 117      navigator.credentials.get({
 118        publicKey
 119      }).then(data => {
 120        const publicKeyCredential = {
 121          id: data.id,
 122          type: data.type,
 123          rawId: arrayToBase64String(new Uint8Array(data.rawId)),
 124          response: {
 125            authenticatorData: arrayToBase64String(new Uint8Array(data.response.authenticatorData)),
 126            clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)),
 127            signature: arrayToBase64String(new Uint8Array(data.response.signature)),
 128            userHandle: data.response.userHandle ? arrayToBase64String(new Uint8Array(data.response.userHandle)) : null
 129          }
 130        };
 131        document.getElementById('users-mfa-code').value = btoa(JSON.stringify(publicKeyCredential));
 132        document.getElementById('users-mfa-captive-form').submit();
 133      }, error => {
 134        // Example: timeout, interaction refused...
 135        handleError(error);
 136      });
 137    };
 138  
 139    const onValidateClick = event => {
 140      event.preventDefault();
 141      authData = JSON.parse(window.atob(Joomla.getOptions('com_users.authData')));
 142      document.getElementById('users-mfa-captive-button-submit').style.disabled = 'disabled';
 143      validate();
 144      return false;
 145    };
 146  
 147    document.getElementById('multifactorauth-webauthn-missing').style.display = 'none';
 148  
 149    if (typeof navigator.credentials === 'undefined') {
 150      document.getElementById('multifactorauth-webauthn-missing').style.display = 'block';
 151      document.getElementById('multifactorauth-webauthn-controls').style.display = 'none';
 152    }
 153  
 154    window.addEventListener('DOMContentLoaded', () => {
 155      if (Joomla.getOptions('com_users.pagetype') === 'validate') {
 156        document.getElementById('users-mfa-captive-button-submit').addEventListener('click', onValidateClick);
 157      } else {
 158        document.querySelectorAll('.multifactorauth_webauthn_setup').forEach(btn => {
 159          btn.addEventListener('click', setUp);
 160        });
 161      }
 162    });
 163  })(Joomla, document);


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer