primo commit
This commit is contained in:
146
media/plg_multifactorauth_webauthn/js/webauthn.js
Normal file
146
media/plg_multifactorauth_webauthn/js/webauthn.js
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Multifactorauth.webauthn
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
((Joomla, document) => {
|
||||
|
||||
let authData = null;
|
||||
const arrayToBase64String = a => btoa(String.fromCharCode(...a));
|
||||
const base64url2base64 = input => {
|
||||
let output = input.replace(/-/g, '+').replace(/_/g, '/');
|
||||
const pad = output.length % 4;
|
||||
if (pad) {
|
||||
if (pad === 1) {
|
||||
throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding');
|
||||
}
|
||||
output += new Array(5 - pad).join('=');
|
||||
}
|
||||
return output;
|
||||
};
|
||||
const displayError = message => {
|
||||
try {
|
||||
Joomla.renderMessages({
|
||||
error: message
|
||||
});
|
||||
} catch (e) {
|
||||
alert(message);
|
||||
}
|
||||
};
|
||||
const handleError = message => {
|
||||
try {
|
||||
document.getElementById('plg_multifactorauth_webauthn_validate_button').style.disabled = 'null';
|
||||
} catch (e) {
|
||||
// Do nothing
|
||||
}
|
||||
displayError(message);
|
||||
};
|
||||
const setUp = e => {
|
||||
e.preventDefault();
|
||||
|
||||
// Make sure the browser supports Webauthn
|
||||
if (!('credentials' in navigator)) {
|
||||
displayError(Joomla.Text._('PLG_MULTIFACTORAUTH_WEBAUTHN_ERR_NOTAVAILABLE_HEAD'));
|
||||
return false;
|
||||
}
|
||||
const rawPKData = document.forms['com-users-method-edit'].querySelectorAll('input[name="pkRequest"]')[0].value;
|
||||
const publicKey = JSON.parse(atob(rawPKData));
|
||||
|
||||
// Convert the public key information to a format usable by the browser's credentials manager
|
||||
publicKey.challenge = Uint8Array.from(window.atob(base64url2base64(publicKey.challenge)), c => c.charCodeAt(0));
|
||||
publicKey.user.id = Uint8Array.from(window.atob(publicKey.user.id), c => c.charCodeAt(0));
|
||||
if (publicKey.excludeCredentials) {
|
||||
publicKey.excludeCredentials = publicKey.excludeCredentials.map(data => {
|
||||
data.id = Uint8Array.from(window.atob(base64url2base64(data.id)), c => c.charCodeAt(0));
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
// Ask the browser to prompt the user for their authenticator
|
||||
navigator.credentials.create({
|
||||
publicKey
|
||||
}).then(data => {
|
||||
const publicKeyCredential = {
|
||||
id: data.id,
|
||||
type: data.type,
|
||||
rawId: arrayToBase64String(new Uint8Array(data.rawId)),
|
||||
response: {
|
||||
clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)),
|
||||
attestationObject: arrayToBase64String(new Uint8Array(data.response.attestationObject))
|
||||
}
|
||||
};
|
||||
|
||||
// Store the WebAuthn reply
|
||||
document.getElementById('com-users-method-code').value = btoa(JSON.stringify(publicKeyCredential));
|
||||
|
||||
// Submit the form
|
||||
document.forms['com-users-method-edit'].submit();
|
||||
}, error => {
|
||||
// An error occurred: timeout, request to provide the authenticator refused, hardware / software
|
||||
// error...
|
||||
handleError(error);
|
||||
});
|
||||
return false;
|
||||
};
|
||||
const validate = () => {
|
||||
// Make sure the browser supports Webauthn
|
||||
if (!('credentials' in navigator)) {
|
||||
displayError(Joomla.Text._('PLG_MULTIFACTORAUTH_WEBAUTHN_ERR_NOTAVAILABLE_HEAD'));
|
||||
return;
|
||||
}
|
||||
const publicKey = authData;
|
||||
if (!publicKey.challenge) {
|
||||
handleError(Joomla.Text._('PLG_MULTIFACTORAUTH_WEBAUTHN_ERR_NO_STORED_CREDENTIAL'));
|
||||
return;
|
||||
}
|
||||
publicKey.challenge = Uint8Array.from(window.atob(base64url2base64(publicKey.challenge)), c => c.charCodeAt(0));
|
||||
if (publicKey.allowCredentials) {
|
||||
publicKey.allowCredentials = publicKey.allowCredentials.map(data => {
|
||||
data.id = Uint8Array.from(window.atob(base64url2base64(data.id)), c => c.charCodeAt(0));
|
||||
return data;
|
||||
});
|
||||
}
|
||||
navigator.credentials.get({
|
||||
publicKey
|
||||
}).then(data => {
|
||||
const publicKeyCredential = {
|
||||
id: data.id,
|
||||
type: data.type,
|
||||
rawId: arrayToBase64String(new Uint8Array(data.rawId)),
|
||||
response: {
|
||||
authenticatorData: arrayToBase64String(new Uint8Array(data.response.authenticatorData)),
|
||||
clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)),
|
||||
signature: arrayToBase64String(new Uint8Array(data.response.signature)),
|
||||
userHandle: data.response.userHandle ? arrayToBase64String(new Uint8Array(data.response.userHandle)) : null
|
||||
}
|
||||
};
|
||||
document.getElementById('users-mfa-code').value = btoa(JSON.stringify(publicKeyCredential));
|
||||
document.getElementById('users-mfa-captive-form').submit();
|
||||
}, error => {
|
||||
// Example: timeout, interaction refused...
|
||||
handleError(error);
|
||||
});
|
||||
};
|
||||
const onValidateClick = event => {
|
||||
event.preventDefault();
|
||||
authData = JSON.parse(window.atob(Joomla.getOptions('com_users.authData')));
|
||||
document.getElementById('users-mfa-captive-button-submit').style.disabled = 'disabled';
|
||||
validate();
|
||||
return false;
|
||||
};
|
||||
document.getElementById('multifactorauth-webauthn-missing').style.display = 'none';
|
||||
if (typeof navigator.credentials === 'undefined') {
|
||||
document.getElementById('multifactorauth-webauthn-missing').style.display = 'block';
|
||||
document.getElementById('multifactorauth-webauthn-controls').style.display = 'none';
|
||||
}
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
if (Joomla.getOptions('com_users.pagetype') === 'validate') {
|
||||
document.getElementById('users-mfa-captive-button-submit').addEventListener('click', onValidateClick);
|
||||
} else {
|
||||
document.querySelectorAll('.multifactorauth_webauthn_setup').forEach(btn => btn.addEventListener('click', setUp));
|
||||
}
|
||||
});
|
||||
})(Joomla, document);
|
||||
7
media/plg_multifactorauth_webauthn/js/webauthn.min.js
vendored
Normal file
7
media/plg_multifactorauth_webauthn/js/webauthn.min.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Multifactorauth.webauthn
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/((s,a)=>{let c=null;const i=t=>btoa(String.fromCharCode(...t)),l=t=>{let e=t.replace(/-/g,"+").replace(/_/g,"/");const r=e.length%4;if(r){if(r===1)throw new Error("InvalidLengthError: Input base64url string is the wrong length to determine padding");e+=new Array(5-r).join("=")}return e},o=t=>{try{s.renderMessages({error:t})}catch{alert(t)}},d=t=>{try{a.getElementById("plg_multifactorauth_webauthn_validate_button").style.disabled="null"}catch{}o(t)},y=t=>{if(t.preventDefault(),!("credentials"in navigator))return o(s.Text._("PLG_MULTIFACTORAUTH_WEBAUTHN_ERR_NOTAVAILABLE_HEAD")),!1;const e=a.forms["com-users-method-edit"].querySelectorAll('input[name="pkRequest"]')[0].value,r=JSON.parse(atob(e));return r.challenge=Uint8Array.from(window.atob(l(r.challenge)),n=>n.charCodeAt(0)),r.user.id=Uint8Array.from(window.atob(r.user.id),n=>n.charCodeAt(0)),r.excludeCredentials&&(r.excludeCredentials=r.excludeCredentials.map(n=>(n.id=Uint8Array.from(window.atob(l(n.id)),u=>u.charCodeAt(0)),n))),navigator.credentials.create({publicKey:r}).then(n=>{const u={id:n.id,type:n.type,rawId:i(new Uint8Array(n.rawId)),response:{clientDataJSON:i(new Uint8Array(n.response.clientDataJSON)),attestationObject:i(new Uint8Array(n.response.attestationObject))}};a.getElementById("com-users-method-code").value=btoa(JSON.stringify(u)),a.forms["com-users-method-edit"].submit()},n=>{d(n)}),!1},p=()=>{if(!("credentials"in navigator)){o(s.Text._("PLG_MULTIFACTORAUTH_WEBAUTHN_ERR_NOTAVAILABLE_HEAD"));return}const t=c;if(!t.challenge){d(s.Text._("PLG_MULTIFACTORAUTH_WEBAUTHN_ERR_NO_STORED_CREDENTIAL"));return}t.challenge=Uint8Array.from(window.atob(l(t.challenge)),e=>e.charCodeAt(0)),t.allowCredentials&&(t.allowCredentials=t.allowCredentials.map(e=>(e.id=Uint8Array.from(window.atob(l(e.id)),r=>r.charCodeAt(0)),e))),navigator.credentials.get({publicKey:t}).then(e=>{const r={id:e.id,type:e.type,rawId:i(new Uint8Array(e.rawId)),response:{authenticatorData:i(new Uint8Array(e.response.authenticatorData)),clientDataJSON:i(new Uint8Array(e.response.clientDataJSON)),signature:i(new Uint8Array(e.response.signature)),userHandle:e.response.userHandle?i(new Uint8Array(e.response.userHandle)):null}};a.getElementById("users-mfa-code").value=btoa(JSON.stringify(r)),a.getElementById("users-mfa-captive-form").submit()},e=>{d(e)})},g=t=>(t.preventDefault(),c=JSON.parse(window.atob(s.getOptions("com_users.authData"))),a.getElementById("users-mfa-captive-button-submit").style.disabled="disabled",p(),!1);a.getElementById("multifactorauth-webauthn-missing").style.display="none",typeof navigator.credentials>"u"&&(a.getElementById("multifactorauth-webauthn-missing").style.display="block",a.getElementById("multifactorauth-webauthn-controls").style.display="none"),window.addEventListener("DOMContentLoaded",()=>{s.getOptions("com_users.pagetype")==="validate"?a.getElementById("users-mfa-captive-button-submit").addEventListener("click",g):a.querySelectorAll(".multifactorauth_webauthn_setup").forEach(t=>t.addEventListener("click",y))})})(Joomla,document);
|
||||
BIN
media/plg_multifactorauth_webauthn/js/webauthn.min.js.gz
Normal file
BIN
media/plg_multifactorauth_webauthn/js/webauthn.min.js.gz
Normal file
Binary file not shown.
Reference in New Issue
Block a user