[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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);
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |