updated plugin WP-WebAuthn version 1.4.1
This commit is contained in:
@ -33,7 +33,8 @@ function updateLog() {
|
||||
url: php_vars.ajax_url,
|
||||
type: 'GET',
|
||||
data: {
|
||||
action: 'wwa_get_log'
|
||||
action: 'wwa_get_log',
|
||||
_ajax_nonce: php_vars._ajax_nonce
|
||||
},
|
||||
success: function (data) {
|
||||
if (typeof data === 'string') {
|
||||
@ -71,7 +72,8 @@ jQuery('#clear_log').click((e) => {
|
||||
url: php_vars.ajax_url,
|
||||
type: 'GET',
|
||||
data: {
|
||||
action: 'wwa_clear_log'
|
||||
action: 'wwa_clear_log',
|
||||
_ajax_nonce: php_vars._ajax_nonce
|
||||
},
|
||||
success: function () {
|
||||
updateLog();
|
||||
|
||||
@ -8,44 +8,44 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
return;
|
||||
}
|
||||
window.onload = () => {
|
||||
if (php_vars.webauthn_only === 'true') {
|
||||
if (wwa_login_php_vars.webauthn_only === 'true') {
|
||||
if ((window.PublicKeyCredential === undefined || navigator.credentials.create === undefined || typeof navigator.credentials.create !== 'function')) {
|
||||
// Not support, show a message
|
||||
if (document.querySelectorAll('#login > h1').length > 0) {
|
||||
let dom = document.createElement('p');
|
||||
dom.className = 'message';
|
||||
dom.innerHTML = php_vars.i18n_8;
|
||||
dom.innerHTML = wwa_login_php_vars.i18n_8;
|
||||
document.querySelectorAll('#login > h1')[0].parentNode.insertBefore(dom, document.querySelectorAll('#login > h1')[0].nextElementSibling)
|
||||
}
|
||||
}
|
||||
wwa_dom('#loginform', (dom) => { dom.classList.add('wwa-webauthn-only') });
|
||||
if (document.getElementsByClassName('user-pass-wrap').length > 0) {
|
||||
wwa_dom('.user-pass-wrap, #wp-submit', (dom) => { dom.parentNode.removeChild(dom) });
|
||||
if (php_vars.remember_me === 'false' ) {
|
||||
if (wwa_login_php_vars.remember_me === 'false' ) {
|
||||
wwa_dom('.forgetmenot', (dom) => { dom.parentNode.removeChild(dom) });
|
||||
}
|
||||
} else {
|
||||
// WordPress 5.2-
|
||||
wwa_dom('#wp-submit', (dom) => { dom.parentNode.removeChild(dom) });
|
||||
if (php_vars.remember_me === 'false' ) {
|
||||
if (wwa_login_php_vars.remember_me === 'false' ) {
|
||||
wwa_dom('.forgetmenot', (dom) => { dom.parentNode.removeChild(dom) });
|
||||
}
|
||||
const targetDOM = document.getElementById('loginform').getElementsByTagName('p')[1];
|
||||
targetDOM.parentNode.removeChild(targetDOM);
|
||||
}
|
||||
}
|
||||
if (!(window.PublicKeyCredential === undefined || navigator.credentials.create === undefined || typeof navigator.credentials.create !== 'function') || php_vars.webauthn_only === 'true') {
|
||||
if (!(window.PublicKeyCredential === undefined || navigator.credentials.create === undefined || typeof navigator.credentials.create !== 'function') || wwa_login_php_vars.webauthn_only === 'true') {
|
||||
// If supported, toggle
|
||||
if (php_vars.webauthn_only !== 'true') {
|
||||
if (wwa_login_php_vars.webauthn_only !== 'true') {
|
||||
if (document.getElementsByClassName('user-pass-wrap').length > 0) {
|
||||
wwa_dom('.user-pass-wrap, #wp-submit', (dom) => { dom.style.display = 'none' });
|
||||
if (php_vars.remember_me === 'false' ) {
|
||||
if (wwa_login_php_vars.remember_me === 'false' ) {
|
||||
wwa_dom('.forgetmenot', (dom) => { dom.style.display = 'none' });
|
||||
}
|
||||
} else {
|
||||
// WordPress 5.2-
|
||||
wwa_dom('#wp-submit', (dom) => { dom.style.display = 'none' });
|
||||
if (php_vars.remember_me === 'false' ) {
|
||||
if (wwa_login_php_vars.remember_me === 'false' ) {
|
||||
wwa_dom('.forgetmenot', (dom) => { dom.style.display = 'none' });
|
||||
}
|
||||
document.getElementById('loginform').getElementsByTagName('p')[1].style.display = 'none';
|
||||
@ -53,8 +53,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.style.display = 'flex' }, 'class');
|
||||
wwa_dom('wp-webauthn-check', (dom) => { dom.style.cssText = `${dom.style.cssText}display: block !important` }, 'id');
|
||||
wwa_dom('user_login', (dom) => { dom.focus() }, 'id');
|
||||
wwa_dom('user_login', (dom) => {
|
||||
dom.setAttribute('autocomplete', 'username webauthn');
|
||||
setTimeout(() => {
|
||||
dom.focus();
|
||||
}, 0);
|
||||
}, 'id');
|
||||
wwa_dom('wp-submit', (dom) => { dom.disabled = true }, 'id');
|
||||
// Start Conditional UI (passkey autofill) once WebAuthn mode is active
|
||||
if (typeof wwa_start_conditional_ui === 'function') {
|
||||
wwa_start_conditional_ui();
|
||||
}
|
||||
}
|
||||
if (document.querySelectorAll('#lostpasswordform, #registerform, .admin-email-confirm-form, #resetpassform').length > 0) {
|
||||
return;
|
||||
@ -64,9 +73,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (dom.length > 0) {
|
||||
if (dom[0].getElementsByTagName('input').length > 0) {
|
||||
// WordPress 5.2-
|
||||
dom[0].innerHTML = `<span id="wwa-username-label">${php_vars.email_login === 'true' ? php_vars.i18n_10 : php_vars.i18n_9}</span>${dom[0].innerHTML.split('<br>')[1]}`;
|
||||
dom[0].innerHTML = `<span id="wwa-username-label">${wwa_login_php_vars.email_login === 'true' ? wwa_login_php_vars.i18n_10 : wwa_login_php_vars.i18n_9}</span>${dom[0].innerHTML.split('<br>')[1]}`;
|
||||
} else {
|
||||
dom[0].innerText = php_vars.email_login === 'true' ? php_vars.i18n_10 : php_vars.i18n_9;
|
||||
dom[0].innerText = wwa_login_php_vars.email_login === 'true' ? wwa_login_php_vars.i18n_10 : wwa_login_php_vars.i18n_9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -305,7 +305,8 @@ function wwa_bind() {
|
||||
alert(wwa_php_vars.i18n_12);
|
||||
return;
|
||||
}
|
||||
let wwa_type = this.parentNode.parentNode.getElementsByClassName('wwa-authenticator-type')[0].value;
|
||||
const wwa_type_el = this.parentNode.parentNode.getElementsByClassName('wwa-authenticator-type')[0];
|
||||
let wwa_type = wwa_type_el ? wwa_type_el.value : (wwa_php_vars.allow_authenticator_type !== 'none' ? wwa_php_vars.allow_authenticator_type : 'none');
|
||||
let wwa_usernameless = this.parentNode.parentNode.querySelectorAll('.wwa-authenticator-usernameless:checked')[0] ? this.parentNode.parentNode.querySelectorAll('.wwa-authenticator-usernameless:checked')[0].value : 'false';
|
||||
button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_3;
|
||||
wwa_disable_buttons();
|
||||
@ -314,7 +315,7 @@ function wwa_bind() {
|
||||
wwa_dom('wwa-authenticator-type', (dom) => { dom.disabled = true }, 'class');
|
||||
wwa_dom('wwa-authenticator-usernameless', (dom) => { dom.disabled = true }, 'class');
|
||||
let request = wwa_ajax();
|
||||
request.get(wwa_php_vars.ajax_url, `?action=wwa_create&name=${encodeURIComponent(wwa_name)}&type=${encodeURIComponent(wwa_type)}&usernameless=${wwa_usernameless}`, (rawData, status) => {
|
||||
request.get(wwa_php_vars.ajax_url, `?action=wwa_create&name=${encodeURIComponent(wwa_name)}&type=${encodeURIComponent(wwa_type)}&usernameless=${wwa_usernameless}&_ajax_nonce=${wwa_php_vars._ajax_nonce}`, (rawData, status) => {
|
||||
if (status) {
|
||||
button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_28;
|
||||
let data = rawData;
|
||||
@ -381,7 +382,7 @@ function wwa_bind() {
|
||||
return publicKeyCredential;
|
||||
}).then(JSON.stringify).then((AuthenticatorAttestationResponse) => {
|
||||
let response = wwa_ajax();
|
||||
response.post(`${wwa_php_vars.ajax_url}?action=wwa_create_response`, `data=${encodeURIComponent(window.btoa(AuthenticatorAttestationResponse))}&name=${encodeURIComponent(wwa_name)}&type=${encodeURIComponent(wwa_type)}&usernameless=${wwa_usernameless}&clientid=${clientID}`, (rawData, status) => {
|
||||
response.post(`${wwa_php_vars.ajax_url}?action=wwa_create_response`, `data=${encodeURIComponent(window.btoa(AuthenticatorAttestationResponse))}&name=${encodeURIComponent(wwa_name)}&type=${encodeURIComponent(wwa_type)}&usernameless=${wwa_usernameless}&clientid=${clientID}&_ajax_nonce=${wwa_php_vars._ajax_nonce}`, (rawData, status) => {
|
||||
if (status) {
|
||||
if (rawData === 'true') {
|
||||
button_dom.nextElementSibling.innerHTML = wwa_php_vars.i18n_29;
|
||||
@ -521,19 +522,33 @@ function wwa_verify() {
|
||||
}
|
||||
|
||||
// Update authenticator list
|
||||
// Compute current number of visible columns for colspan
|
||||
function getFrontendColspan() {
|
||||
let cols = 4; // Identifier, Registered, Last used, Action
|
||||
const typeTh = document.getElementsByClassName('wwa-type-th')[0];
|
||||
if (typeTh && typeTh.style.display !== 'none') {
|
||||
cols++;
|
||||
}
|
||||
const ulTh = document.getElementsByClassName('wwa-usernameless-th')[0];
|
||||
if (ulTh && ulTh.style.display !== 'none') {
|
||||
cols++;
|
||||
}
|
||||
return cols;
|
||||
}
|
||||
|
||||
function updateList() {
|
||||
if (document.getElementsByClassName('wwa-authenticator-list').length === 0) {
|
||||
return;
|
||||
}
|
||||
let request = wwa_ajax();
|
||||
request.get(wwa_php_vars.ajax_url, '?action=wwa_authenticator_list', (rawData, status) => {
|
||||
request.get(wwa_php_vars.ajax_url, `?action=wwa_authenticator_list&_ajax_nonce=${wwa_php_vars._ajax_nonce}`, (rawData, status) => {
|
||||
if (status) {
|
||||
let data = rawData;
|
||||
try {
|
||||
data = JSON.parse(rawData);
|
||||
} catch (e) {
|
||||
console.warn(rawData);
|
||||
wwa_dom('wwa-authenticator-list', (dom) => { dom.innerHTML = `<tr><td colspan="${document.getElementsByClassName('wwa-usernameless-th')[0].style.display === 'none' ? '5' : '6'}">${wwa_php_vars.i18n_17}</td></tr>` }, 'class');
|
||||
wwa_dom('wwa-authenticator-list', (dom) => { dom.innerHTML = `<tr><td colspan="${getFrontendColspan()}">${wwa_php_vars.i18n_17}</td></tr>` }, 'class');
|
||||
return;
|
||||
}
|
||||
if (data.length === 0) {
|
||||
@ -542,7 +557,7 @@ function updateList() {
|
||||
} else {
|
||||
wwa_dom('.wwa-usernameless-th, .wwa-usernameless-td', (dom) => { dom.style.display = 'none' });
|
||||
}
|
||||
wwa_dom('wwa-authenticator-list', (dom) => { dom.innerHTML = `<tr><td colspan="${document.getElementsByClassName('wwa-usernameless-th')[0].style.display === 'none' ? '5' : '6'}">${wwa_php_vars.i18n_23}</td></tr>` }, 'class');
|
||||
wwa_dom('wwa-authenticator-list', (dom) => { dom.innerHTML = `<tr><td colspan="${getFrontendColspan()}">${wwa_php_vars.i18n_23}</td></tr>` }, 'class');
|
||||
wwa_dom('wwa-authenticator-list-usernameless-tip', (dom) => { dom.innerText = '' }, 'class');
|
||||
wwa_dom('wwa-authenticator-list-type-tip', (dom) => { dom.innerText = '' }, 'class');
|
||||
return;
|
||||
@ -561,7 +576,7 @@ function updateList() {
|
||||
item_type_disabled = true;
|
||||
}
|
||||
}
|
||||
htmlStr += `<tr><td>${item.name}</td><td>${item.type === 'none' ? wwa_php_vars.i18n_24 : (item.type === 'platform' ? wwa_php_vars.i18n_25 : wwa_php_vars.i18n_26)}${item_type_disabled ? wwa_php_vars.i18n_35 : ''}</td><td>${item.added}</td><td>${item.last_used}</td><td class="wwa-usernameless-td">${item.usernameless ? wwa_php_vars.i18n_1 + (wwa_php_vars.usernameless === 'true' ? '' : wwa_php_vars.i18n_9) : wwa_php_vars.i18n_8}</td><td class="wwa-key-${item.key}"><a href="javascript:renameAuthenticator('${item.key}', '${item.name.replaceAll('\'', '\\\'').replaceAll(''', '\\'').replaceAll('"', '\\"')}')">${wwa_php_vars.i18n_20}</a> | <a href="javascript:removeAuthenticator('${item.key}', '${item.name.replaceAll('\'', '\\\'').replaceAll(''', '\\'').replaceAll('"', '\\"')}')">${wwa_php_vars.i18n_27}</a></td></tr>`;
|
||||
htmlStr += `<tr><td>${item.name}</td>${wwa_php_vars.show_authenticator_type === 'true' ? `<td class="wwa-type-td">${item.type === 'none' ? wwa_php_vars.i18n_24 : (item.type === 'platform' ? wwa_php_vars.i18n_25 : wwa_php_vars.i18n_26)}${item_type_disabled ? wwa_php_vars.i18n_35 : ''}</td>` : ''}<td>${item.added}</td><td>${item.last_used}</td><td class="wwa-usernameless-td">${item.usernameless ? wwa_php_vars.i18n_1 + (wwa_php_vars.usernameless === 'true' ? '' : wwa_php_vars.i18n_9) : wwa_php_vars.i18n_8}</td><td class="wwa-key-${item.key}"><a href="javascript:renameAuthenticator('${item.key}', '${item.name.replaceAll('\'', '\\\'').replaceAll(''', '\\'').replaceAll('"', '\\"')}')">${wwa_php_vars.i18n_20}</a> | <a href="javascript:removeAuthenticator('${item.key}', '${item.name.replaceAll('\'', '\\\'').replaceAll(''', '\\'').replaceAll('"', '\\"')}')">${wwa_php_vars.i18n_27}</a></td></tr>`;
|
||||
}
|
||||
wwa_dom('wwa-authenticator-list', (dom) => { dom.innerHTML = htmlStr }, 'class');
|
||||
if (has_usernameless || wwa_php_vars.usernameless === 'true') {
|
||||
@ -586,7 +601,7 @@ function updateList() {
|
||||
wwa_dom('wwa-authenticator-list-type-tip', (dom) => { dom.innerText = ''; dom.style.display = 'none' }, 'class');
|
||||
}
|
||||
} else {
|
||||
wwa_dom('wwa-authenticator-list', (dom) => { dom.innerHTML = `<tr><td colspan="${document.getElementsByClassName('wwa-usernameless-th')[0].style.display === 'none' ? '5' : '6'}">${wwa_php_vars.i18n_17}</td></tr>` }, 'class');
|
||||
wwa_dom('wwa-authenticator-list', (dom) => { dom.innerHTML = `<tr><td colspan="${getFrontendColspan()}">${wwa_php_vars.i18n_17}</td></tr>` }, 'class');
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -603,7 +618,7 @@ function renameAuthenticator(id, name) {
|
||||
} else if (new_name !== null && new_name !== name) {
|
||||
let request = wwa_ajax();
|
||||
wwa_dom(`wwa-key-${id}`, (dom) => { dom.innerText = wwa_php_vars.i18n_22 }, 'class');
|
||||
request.get(wwa_php_vars.ajax_url, `?action=wwa_modify_authenticator&id=${encodeURIComponent(id)}&name=${encodeURIComponent(new_name)}&target=rename`, (data, status) => {
|
||||
request.get(wwa_php_vars.ajax_url, `?action=wwa_modify_authenticator&id=${encodeURIComponent(id)}&name=${encodeURIComponent(new_name)}&target=rename&_ajax_nonce=${wwa_php_vars._ajax_nonce}`, (data, status) => {
|
||||
if (status) {
|
||||
updateList();
|
||||
} else {
|
||||
@ -623,7 +638,7 @@ function removeAuthenticator(id, name) {
|
||||
if (confirm(wwa_php_vars.i18n_18 + name + (document.getElementsByClassName('wwa-authenticator-list')[0].children.length === 1 ? '\n' + wwa_php_vars.i18n_34 : ''))) {
|
||||
wwa_dom(`wwa-key-${id}`, (dom) => { dom.innerText = wwa_php_vars.i18n_19 }, 'class');
|
||||
let request = wwa_ajax();
|
||||
request.get(wwa_php_vars.ajax_url, `?action=wwa_modify_authenticator&id=${encodeURIComponent(id)}&target=remove`, (data, status) => {
|
||||
request.get(wwa_php_vars.ajax_url, `?action=wwa_modify_authenticator&id=${encodeURIComponent(id)}&target=remove&_ajax_nonce=${wwa_php_vars._ajax_nonce}`, (data, status) => {
|
||||
if (status) {
|
||||
updateList();
|
||||
} else {
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const wwa_passkey_notice_svg = '<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background:new 0 0 216 216;width:28px" viewBox="0 0 216 216"><style>.st2{fill-rule:evenodd;clip-rule:evenodd}</style><g id="Isolation_Mode"><path d="M0 0h216v216H0z" style="fill:none"/><path d="M172.32 96.79c0 13.78-8.48 25.5-20.29 29.78l7.14 11.83-10.57 13 10.57 12.71-17.04 22.87-12.01-12.82V125.7c-10.68-4.85-18.15-15.97-18.15-28.91 0-17.4 13.51-31.51 30.18-31.51 16.66 0 30.17 14.11 30.17 31.51zm-30.18 4.82c4.02 0 7.28-3.4 7.28-7.6 0-4.2-3.26-7.61-7.28-7.61s-7.28 3.4-7.28 7.61c-.01 4.2 3.26 7.6 7.28 7.6z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#353535"/><path d="M172.41 96.88c0 13.62-8.25 25.23-19.83 29.67l6.58 11.84-9.73 13 9.73 12.71-17.03 23.05v-85.54c4.02 0 7.28-3.41 7.28-7.6 0-4.2-3.26-7.61-7.28-7.61V65.28c16.73 0 30.28 14.15 30.28 31.6zM120.24 131.43c-9.75-8-16.3-20.3-17.2-34.27H50.8c-10.96 0-19.84 9.01-19.84 20.13v25.17c0 5.56 4.44 10.07 9.92 10.07h69.44c5.48 0 9.92-4.51 9.92-10.07v-11.03z" class="st2"/><path d="M73.16 91.13c-2.42-.46-4.82-.89-7.11-1.86-8.65-3.63-13.69-10.32-15.32-19.77-1.12-6.47-.59-12.87 2.03-18.92 3.72-8.6 10.39-13.26 19.15-14.84 5.24-.94 10.46-.73 15.5 1.15 7.59 2.82 12.68 8.26 15.03 16.24 2.38 8.05 2.03 16.1-1.56 23.72-3.72 7.96-10.21 12.23-18.42 13.9-.68.14-1.37.27-2.05.41-2.41-.03-4.83-.03-7.25-.03z" style="fill:#141313"/></g></svg>';
|
||||
const wwa_passkey_btn_svg = '<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background:new 0 0 216 216;width:28px" viewBox="0 0 216 216"><style>.st2{fill-rule:evenodd;clip-rule:evenodd}</style><g id="Isolation_Mode"><path d="M0 0h216v216H0z" style="fill:none"/><path d="M172.32 96.79c0 13.78-8.48 25.5-20.29 29.78l7.14 11.83-10.57 13 10.57 12.71-17.04 22.87-12.01-12.82V125.7c-10.68-4.85-18.15-15.97-18.15-28.91 0-17.4 13.51-31.51 30.18-31.51 16.66 0 30.17 14.11 30.17 31.51zm-30.18 4.82c4.02 0 7.28-3.4 7.28-7.6 0-4.2-3.26-7.61-7.28-7.61s-7.28 3.4-7.28 7.61c-.01 4.2 3.26 7.6 7.28 7.6z" style="fill-rule:evenodd;clip-rule:evenodd;fill:currentcolor"/><path d="M172.41 96.88c0 13.62-8.25 25.23-19.83 29.67l6.58 11.84-9.73 13 9.73 12.71-17.03 23.05v-85.54c4.02 0 7.28-3.41 7.28-7.6 0-4.2-3.26-7.61-7.28-7.61V65.28c16.73 0 30.28 14.15 30.28 31.6zM120.24 131.43c-9.75-8-16.3-20.3-17.2-34.27H50.8c-10.96 0-19.84 9.01-19.84 20.13v25.17c0 5.56 4.44 10.07 9.92 10.07h69.44c5.48 0 9.92-4.51 9.92-10.07v-11.03z" class="st2" style="fill:currentcolor"/><path d="M73.16 91.13c-2.42-.46-4.82-.89-7.11-1.86-8.65-3.63-13.69-10.32-15.32-19.77-1.12-6.47-.59-12.87 2.03-18.92 3.72-8.6 10.39-13.26 19.15-14.84 5.24-.94 10.46-.73 15.5 1.15 7.59 2.82 12.68 8.26 15.03 16.24 2.38 8.05 2.03 16.1-1.56 23.72-3.72 7.96-10.21 12.23-18.42 13.9-.68.14-1.37.27-2.05.41-2.41-.03-4.83-.03-7.25-.03z" style="fill:currentcolor"/></g></svg>';
|
||||
|
||||
// Send an AJAX request and get the response
|
||||
const wwa_ajax = function () {
|
||||
let xmlHttpReq = new XMLHttpRequest();
|
||||
@ -70,19 +73,154 @@ const wwa_dom = (selector, callback = () => { }, method = 'query') => {
|
||||
}
|
||||
|
||||
let wwaSupported = true;
|
||||
let wwa_conditional_ui_abort = null;
|
||||
let wwa_conditional_ui_active = false;
|
||||
|
||||
/**
|
||||
* Start a Conditional UI (passkey autofill) request.
|
||||
* The browser will show a passkey picker in the username autocomplete dropdown.
|
||||
* Aborted automatically when the user manually triggers a normal WebAuthn check.
|
||||
*/
|
||||
function wwa_start_conditional_ui() {
|
||||
if (wwa_conditional_ui_active) return;
|
||||
if (!window.PublicKeyCredential) return;
|
||||
|
||||
// Prefer getClientCapabilities() (Chrome 128+) for a richer capability check;
|
||||
// fall back to isConditionalMediationAvailable() for older browsers.
|
||||
const conditionalAvailablePromise =
|
||||
typeof PublicKeyCredential.getClientCapabilities === 'function'
|
||||
? PublicKeyCredential.getClientCapabilities().then((caps) => !!caps.conditionalGet)
|
||||
: typeof PublicKeyCredential.isConditionalMediationAvailable === 'function'
|
||||
? PublicKeyCredential.isConditionalMediationAvailable()
|
||||
: Promise.resolve(false);
|
||||
|
||||
conditionalAvailablePromise.then((available) => {
|
||||
if (!available) return;
|
||||
|
||||
wwa_conditional_ui_active = true;
|
||||
wwa_conditional_ui_abort = new AbortController();
|
||||
const signal = wwa_conditional_ui_abort.signal;
|
||||
|
||||
// Request an empty-user challenge (usernameless style: no allowCredentials)
|
||||
let startReq = wwa_ajax();
|
||||
startReq.get(wwa_login_php_vars.ajax_url,
|
||||
'?action=wwa_auth_start&type=auth&usernameless=true&conditional=true',
|
||||
(rawData, status) => {
|
||||
if (!status || signal.aborted) {
|
||||
wwa_conditional_ui_active = false;
|
||||
return;
|
||||
}
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(rawData);
|
||||
} catch (e) {
|
||||
wwa_conditional_ui_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
data.challenge = Uint8Array.from(
|
||||
window.atob(base64url2base64(data.challenge)),
|
||||
(c) => c.charCodeAt(0)
|
||||
);
|
||||
if (data.allowCredentials) {
|
||||
data.allowCredentials = data.allowCredentials.map((item) => {
|
||||
item.id = Uint8Array.from(
|
||||
window.atob(base64url2base64(item.id)),
|
||||
(c) => c.charCodeAt(0)
|
||||
);
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
const clientID = data.clientID;
|
||||
delete data.clientID;
|
||||
|
||||
navigator.credentials.get({
|
||||
publicKey: data,
|
||||
mediation: 'conditional',
|
||||
signal: signal
|
||||
}).then((credentialInfo) => {
|
||||
if (!credentialInfo) {
|
||||
wwa_conditional_ui_active = false;
|
||||
return;
|
||||
}
|
||||
// Show authenticating state
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_5; }, 'class');
|
||||
wwa_dom('user_login', (dom) => { dom.readOnly = true; }, 'id');
|
||||
wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = true; });
|
||||
|
||||
const publicKeyCredential = {
|
||||
id: credentialInfo.id,
|
||||
type: credentialInfo.type,
|
||||
rawId: arrayToBase64String(new Uint8Array(credentialInfo.rawId)),
|
||||
response: {
|
||||
authenticatorData: arrayToBase64String(new Uint8Array(credentialInfo.response.authenticatorData)),
|
||||
clientDataJSON: arrayToBase64String(new Uint8Array(credentialInfo.response.clientDataJSON)),
|
||||
signature: arrayToBase64String(new Uint8Array(credentialInfo.response.signature)),
|
||||
userHandle: credentialInfo.response.userHandle
|
||||
? arrayToBase64String(new Uint8Array(credentialInfo.response.userHandle))
|
||||
: null
|
||||
}
|
||||
};
|
||||
|
||||
const AuthenticatorResponse = JSON.stringify(publicKeyCredential);
|
||||
// The server needs the usernameless path, so username is empty
|
||||
const userField = document.getElementById('user_login');
|
||||
const username = userField ? userField.value : '';
|
||||
|
||||
let response = wwa_ajax();
|
||||
response.post(
|
||||
`${wwa_login_php_vars.ajax_url}?action=wwa_auth`,
|
||||
`data=${encodeURIComponent(window.btoa(AuthenticatorResponse))}&type=auth&clientid=${clientID}&user=${encodeURIComponent(username)}&conditional=true&remember=${wwa_login_php_vars.remember_me === 'false' ? 'false' : (document.getElementById('rememberme') ? (document.getElementById('rememberme').checked ? 'true' : 'false') : 'false')}` ,
|
||||
(resData, resStatus) => {
|
||||
wwa_conditional_ui_active = false;
|
||||
if (resStatus && resData === 'true') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_6; }, 'class');
|
||||
const redirectInput = document.querySelector('p.submit input[name="redirect_to"]');
|
||||
const redirectTo = redirectInput
|
||||
? redirectInput.value
|
||||
: (getQueryString('redirect_to') || wwa_login_php_vars.admin_url);
|
||||
setTimeout(() => { window.location.href = redirectTo; }, 200);
|
||||
} else {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => {
|
||||
dom.innerHTML = wwa_login_php_vars.terminology === 'passkey'
|
||||
? `<span class="wwa-passkey-notice">${wwa_passkey_notice_svg} ${wwa_login_php_vars.i18n_2}</span>`
|
||||
: `<span><span class="dashicons dashicons-shield-alt"></span> ${wwa_login_php_vars.i18n_2}</span>`;
|
||||
}, 'class');
|
||||
wwa_dom('user_login', (dom) => { dom.readOnly = false; }, 'id');
|
||||
wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = false; });
|
||||
// Restart Conditional UI after a failed attempt
|
||||
wwa_start_conditional_ui();
|
||||
}
|
||||
}
|
||||
);
|
||||
}).catch((err) => {
|
||||
wwa_conditional_ui_active = false;
|
||||
// AbortError is expected when check() aborts — do nothing
|
||||
if (err && err.name !== 'AbortError') {
|
||||
console.warn('WP-WebAuthn Conditional UI error:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}).catch(() => {
|
||||
// isConditionalMediationAvailable not supported or threw — silently ignore
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
if (document.querySelector('p#nav') && php_vars.password_reset !== 'false') {
|
||||
if (document.querySelector('p#nav') && wwa_login_php_vars.password_reset !== 'false') {
|
||||
const placeholder = document.getElementById('wwa-lost-password-link-placeholder');
|
||||
if (placeholder) {
|
||||
const previous = placeholder.previousSibling;
|
||||
const next = placeholder.nextElementSibling;
|
||||
if (previous && previous.nodeType === Node.TEXT_NODE && previous.data.trim() === php_vars.separator.trim()) {
|
||||
if (previous && previous.nodeType === Node.TEXT_NODE && previous.data.trim() === wwa_login_php_vars.separator.trim()) {
|
||||
previous.remove();
|
||||
} else if (next && next.nodeType === Node.TEXT_NODE && next.data.trim() === php_vars.separator.trim()) {
|
||||
} else if (next && next.nodeType === Node.TEXT_NODE && next.data.trim() === wwa_login_php_vars.separator.trim() && !next.nextElementSibling) {
|
||||
next.remove();
|
||||
}
|
||||
placeholder.remove();
|
||||
}
|
||||
placeholder.remove();
|
||||
}
|
||||
if (document.querySelectorAll('#lostpasswordform, #registerform, .admin-email-confirm-form, #resetpassform').length > 0) {
|
||||
return;
|
||||
@ -95,24 +233,25 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
button_check.id = 'wp-webauthn-check';
|
||||
button_check.type = 'button';
|
||||
button_check.className = 'button button-large button-primary';
|
||||
button_check.innerHTML = php_vars.i18n_1;
|
||||
button_check.innerHTML = wwa_login_php_vars.i18n_1;
|
||||
let button_toggle = document.createElement('button');
|
||||
if (php_vars.webauthn_only !== 'true') {
|
||||
if (wwa_login_php_vars.webauthn_only !== 'true') {
|
||||
button_toggle.id = 'wp-webauthn';
|
||||
button_toggle.type = 'button';
|
||||
button_toggle.className = 'button button-large';
|
||||
button_toggle.innerHTML = '<span class="dashicons dashicons-update-alt"></span>';
|
||||
button_toggle.innerHTML = '<span class="dashicons dashicons-ellipsis password-icon"></span>';
|
||||
button_toggle.title = wwa_login_php_vars.i18n_13;
|
||||
}
|
||||
let submit = document.getElementById('wp-submit');
|
||||
if (submit) {
|
||||
if (php_vars.webauthn_only !== 'true') {
|
||||
if (wwa_login_php_vars.webauthn_only !== 'true') {
|
||||
submit.parentNode.insertBefore(button_toggle, submit.nextElementSibling);
|
||||
}
|
||||
submit.parentNode.insertBefore(button_check, submit.nextElementSibling);
|
||||
}
|
||||
let notice = document.createElement('div');
|
||||
notice.className = 'wp-webauthn-notice';
|
||||
notice.innerHTML = `<span><span class="dashicons dashicons-shield-alt"></span> ${php_vars.i18n_2}<span>`;
|
||||
notice.innerHTML = wwa_login_php_vars.terminology ==='passkey' ? `<span class="wwa-passkey-notice">${wwa_passkey_notice_svg} ${wwa_login_php_vars.i18n_2}</span>` : `<span><span class="dashicons dashicons-shield-alt"></span> ${wwa_login_php_vars.i18n_2}</span>`;
|
||||
let forgetmenot = document.getElementsByClassName('forgetmenot');
|
||||
if (forgetmenot.length > 0) {
|
||||
forgetmenot[0].parentNode.insertBefore(notice, forgetmenot[0]);
|
||||
@ -211,46 +350,71 @@ function toggle() {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.style.display = 'none' }, 'class');
|
||||
wwa_dom('wp-webauthn-check', (dom) => { dom.style.cssText = `${dom.style.cssText.split('display: block !important')[0]}display: none !important` }, 'id');
|
||||
wwa_dom('user_pass', (dom) => { dom.disabled = false }, 'id');
|
||||
wwa_dom('user_login', (dom) => { dom.focus() }, 'id');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = `<span><span class="dashicons dashicons-shield-alt"></span> ${php_vars.i18n_2}</span>` }, 'class');
|
||||
wwa_dom('user_login', (dom) => {
|
||||
dom.setAttribute('autocomplete', 'username');
|
||||
setTimeout(() => {
|
||||
dom.focus();
|
||||
}, 0);
|
||||
}, 'id');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.terminology ==='passkey' ? `<span class="wwa-passkey-notice">${wwa_passkey_notice_svg} ${wwa_login_php_vars.i18n_2}</span>` : `<span><span class="dashicons dashicons-shield-alt"></span> ${wwa_login_php_vars.i18n_2}</span>` }, 'class');
|
||||
wwa_dom('wp-submit', (dom) => { dom.disabled = false }, 'id');
|
||||
wwa_dom('wp-webauthn', wwa_login_php_vars.terminology ==='passkey' ? (dom) => {
|
||||
dom.innerHTML = wwa_passkey_btn_svg;
|
||||
dom.title = wwa_login_php_vars.i18n_14;
|
||||
dom.style.lineHeight = '0';
|
||||
} : (dom) => {
|
||||
dom.innerHTML = '<span class="dashicons dashicons-shield-alt"></span>';
|
||||
dom.title = wwa_login_php_vars.i18n_14;
|
||||
}, 'id');
|
||||
let inputDom = document.querySelectorAll('#loginform label')
|
||||
if (inputDom.length > 0) {
|
||||
if (document.getElementById('wwa-username-label')) {
|
||||
// WordPress 5.2-
|
||||
document.getElementById('wwa-username-label').innerText = php_vars.i18n_10;
|
||||
document.getElementById('wwa-username-label').innerText = wwa_login_php_vars.i18n_10;
|
||||
} else {
|
||||
inputDom[0].innerText = php_vars.i18n_10;
|
||||
inputDom[0].innerText = wwa_login_php_vars.i18n_10;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (document.getElementsByClassName('user-pass-wrap').length > 0) {
|
||||
wwa_dom('.user-pass-wrap, #wp-submit', (dom) => { dom.style.display = 'none' });
|
||||
if (php_vars.remember_me === 'false' ) {
|
||||
if (wwa_login_php_vars.remember_me === 'false' ) {
|
||||
wwa_dom('.forgetmenot', (dom) => { dom.style.display = 'none' });
|
||||
}
|
||||
} else {
|
||||
// WordPress 5.2-
|
||||
wwa_dom('#wp-submit', (dom) => { dom.style.display = 'none' });
|
||||
if (php_vars.remember_me === 'false' ) {
|
||||
if (wwa_login_php_vars.remember_me === 'false' ) {
|
||||
wwa_dom('.forgetmenot', (dom) => { dom.style.display = 'none' });
|
||||
}
|
||||
document.getElementById('loginform').getElementsByTagName('p')[1].style.display = 'none';
|
||||
}
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.style.display = 'flex' }, 'class');
|
||||
wwa_dom('wp-webauthn-check', (dom) => { dom.style.cssText = `${dom.style.cssText.split('display: none !important')[0]}display: block !important` }, 'id');
|
||||
wwa_dom('user_login', (dom) => { dom.focus() }, 'id');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = `<span><span class="dashicons dashicons-shield-alt"></span> ${php_vars.i18n_2}</span>` }, 'class');
|
||||
wwa_dom('user_login', (dom) => {
|
||||
dom.setAttribute('autocomplete', 'username webauthn');
|
||||
setTimeout(() => {
|
||||
dom.focus();
|
||||
}, 0);
|
||||
}, 'id');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.terminology ==='passkey' ? `<span class="wwa-passkey-notice">${wwa_passkey_notice_svg} ${wwa_login_php_vars.i18n_2}</span>` : `<span><span class="dashicons dashicons-shield-alt"></span> ${wwa_login_php_vars.i18n_2}</span>` }, 'class');
|
||||
wwa_dom('wp-submit', (dom) => { dom.disabled = true }, 'id');
|
||||
wwa_dom('wp-webauthn', (dom) => {
|
||||
dom.innerHTML = '<span class="dashicons dashicons-ellipsis password-icon"></span>';
|
||||
dom.title = wwa_login_php_vars.i18n_13;
|
||||
dom.style.lineHeight = '';
|
||||
}, 'id');
|
||||
let inputDom = document.querySelectorAll('#loginform label')
|
||||
if (inputDom.length > 0) {
|
||||
if (document.getElementById('wwa-username-label')) {
|
||||
// WordPress 5.2-
|
||||
document.getElementById('wwa-username-label').innerText = php_vars.email_login === 'true' ? php_vars.i18n_10 : php_vars.i18n_9;
|
||||
document.getElementById('wwa-username-label').innerText = wwa_login_php_vars.email_login === 'true' ? wwa_login_php_vars.i18n_10 : wwa_login_php_vars.i18n_9;
|
||||
} else {
|
||||
inputDom[0].innerText = php_vars.email_login === 'true' ? php_vars.i18n_10 : php_vars.i18n_9;
|
||||
inputDom[0].innerText = wwa_login_php_vars.email_login === 'true' ? wwa_login_php_vars.i18n_10 : wwa_login_php_vars.i18n_9;
|
||||
}
|
||||
}
|
||||
// Start Conditional UI when switching into WebAuthn mode
|
||||
wwa_start_conditional_ui();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -276,13 +440,13 @@ function check() {
|
||||
return;
|
||||
}
|
||||
if (wwaSupported) {
|
||||
if (document.getElementById('user_login').value === '' && php_vars.usernameless !== 'true') {
|
||||
if (document.getElementById('user_login').value === '' && wwa_login_php_vars.usernameless !== 'true') {
|
||||
wwa_dom('login_error', (dom) => { dom.remove() }, 'id');
|
||||
wwa_dom('p.message', (dom) => { dom.remove() });
|
||||
if (document.querySelectorAll('#login > h1').length > 0) {
|
||||
let dom = document.createElement('div');
|
||||
dom.id = 'login_error';
|
||||
dom.innerHTML = php_vars.i18n_11;
|
||||
dom.innerHTML = wwa_login_php_vars.i18n_11;
|
||||
document.querySelectorAll('#login > h1')[0].parentNode.insertBefore(dom, document.querySelectorAll('#login > h1')[0].nextElementSibling)
|
||||
}
|
||||
// Shake the login form, code from WordPress
|
||||
@ -293,22 +457,28 @@ function check() {
|
||||
wwa_shake(form, shake, 20);
|
||||
return;
|
||||
}
|
||||
// Abort any pending Conditional UI before starting a new modal request
|
||||
if (wwa_conditional_ui_abort) {
|
||||
wwa_conditional_ui_abort.abort();
|
||||
wwa_conditional_ui_abort = null;
|
||||
wwa_conditional_ui_active = false;
|
||||
}
|
||||
wwa_dom('user_login', (dom) => { dom.readOnly = true }, 'id');
|
||||
wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = true });
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_3 }, 'class');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_3 }, 'class');
|
||||
let request = wwa_ajax();
|
||||
request.get(php_vars.ajax_url, `?action=wwa_auth_start&user=${encodeURIComponent(document.getElementById('user_login').value)}&type=auth`, (rawData, status) => {
|
||||
request.get(wwa_login_php_vars.ajax_url, `?action=wwa_auth_start&user=${encodeURIComponent(document.getElementById('user_login').value)}&type=auth`, (rawData, status) => {
|
||||
if (status) {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_4 }, 'class');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_4 }, 'class');
|
||||
let data = rawData;
|
||||
try {
|
||||
data = JSON.parse(rawData);
|
||||
} catch (e) {
|
||||
console.warn(rawData);
|
||||
if (php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 + php_vars.i18n_12 }, 'class');
|
||||
if (wwa_login_php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_7 + wwa_login_php_vars.i18n_12 }, 'class');
|
||||
} else {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 }, 'class');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_7 }, 'class');
|
||||
}
|
||||
wwa_dom('user_login', (dom) => { dom.readOnly = false }, 'id');
|
||||
wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = false });
|
||||
@ -323,11 +493,11 @@ function check() {
|
||||
});
|
||||
}
|
||||
|
||||
if (data.allowCredentials && php_vars.allow_authenticator_type && php_vars.allow_authenticator_type !== 'none') {
|
||||
if (data.allowCredentials && wwa_login_php_vars.allow_authenticator_type && wwa_login_php_vars.allow_authenticator_type !== 'none') {
|
||||
for (let credential of data.allowCredentials) {
|
||||
if (php_vars.allow_authenticator_type === 'cross-platform') {
|
||||
if (wwa_login_php_vars.allow_authenticator_type === 'cross-platform') {
|
||||
credential.transports = ['usb', 'nfc', 'ble'];
|
||||
} else if (php_vars.allow_authenticator_type === 'platform') {
|
||||
} else if (wwa_login_php_vars.allow_authenticator_type === 'platform') {
|
||||
credential.transports = ['internal'];
|
||||
}
|
||||
}
|
||||
@ -338,7 +508,7 @@ function check() {
|
||||
delete data.clientID;
|
||||
|
||||
navigator.credentials.get({ 'publicKey': data }).then((credentialInfo) => {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_5 }, 'class');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_5 }, 'class');
|
||||
return credentialInfo;
|
||||
}).then((data) => {
|
||||
const publicKeyCredential = {
|
||||
@ -355,10 +525,10 @@ function check() {
|
||||
return publicKeyCredential;
|
||||
}).then(JSON.stringify).then((AuthenticatorResponse) => {
|
||||
let response = wwa_ajax();
|
||||
response.post(`${php_vars.ajax_url}?action=wwa_auth`, `data=${encodeURIComponent(window.btoa(AuthenticatorResponse))}&type=auth&clientid=${clientID}&user=${encodeURIComponent(document.getElementById('user_login').value)}&remember=${php_vars.remember_me === 'false' ? 'false' : (document.getElementById('rememberme') ? (document.getElementById('rememberme').checked ? 'true' : 'false') : 'false')}`, (data, status) => {
|
||||
response.post(`${wwa_login_php_vars.ajax_url}?action=wwa_auth`, `data=${encodeURIComponent(window.btoa(AuthenticatorResponse))}&type=auth&clientid=${clientID}&user=${encodeURIComponent(document.getElementById('user_login').value)}&remember=${wwa_login_php_vars.remember_me === 'false' ? 'false' : (document.getElementById('rememberme') ? (document.getElementById('rememberme').checked ? 'true' : 'false') : 'false')}`, (data, status) => {
|
||||
if (status) {
|
||||
if (data === 'true') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_6 }, 'class');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_6 }, 'class');
|
||||
if (document.querySelectorAll('p.submit input[name="redirect_to"]').length > 0) {
|
||||
setTimeout(() => {
|
||||
window.location.href = document.querySelectorAll('p.submit input[name="redirect_to"]')[0].value;
|
||||
@ -370,24 +540,24 @@ function check() {
|
||||
}, 200);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
window.location.href = php_vars.admin_url
|
||||
window.location.href = wwa_login_php_vars.admin_url
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 + php_vars.i18n_12 }, 'class');
|
||||
if (wwa_login_php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_7 + wwa_login_php_vars.i18n_12 }, 'class');
|
||||
} else {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 }, 'class');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_7 }, 'class');
|
||||
}
|
||||
wwa_dom('user_login', (dom) => { dom.readOnly = false }, 'id');
|
||||
wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = false });
|
||||
}
|
||||
} else {
|
||||
if (php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 + php_vars.i18n_12 }, 'class');
|
||||
if (wwa_login_php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_7 + wwa_login_php_vars.i18n_12 }, 'class');
|
||||
} else {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 }, 'class');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_7 }, 'class');
|
||||
}
|
||||
wwa_dom('user_login', (dom) => { dom.readOnly = false }, 'id');
|
||||
wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = false });
|
||||
@ -395,23 +565,23 @@ function check() {
|
||||
})
|
||||
}).catch((error) => {
|
||||
console.warn(error);
|
||||
if (php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 + php_vars.i18n_12 }, 'class');
|
||||
if (wwa_login_php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_7 + wwa_login_php_vars.i18n_12 }, 'class');
|
||||
} else {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 }, 'class');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_7 }, 'class');
|
||||
}
|
||||
wwa_dom('user_login', (dom) => { dom.readOnly = false }, 'id');
|
||||
wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = false });
|
||||
})
|
||||
} else {
|
||||
if (php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 + php_vars.i18n_12 }, 'class');
|
||||
if (wwa_login_php_vars.usernameless === 'true' && document.getElementById('user_login').value === '') {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_7 + wwa_login_php_vars.i18n_12 }, 'class');
|
||||
} else {
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = php_vars.i18n_7 }, 'class');
|
||||
wwa_dom('wp-webauthn-notice', (dom) => { dom.innerHTML = wwa_login_php_vars.i18n_7 }, 'class');
|
||||
}
|
||||
wwa_dom('user_login', (dom) => { dom.readOnly = false }, 'id');
|
||||
wwa_dom('#wp-webauthn-check, #wp-webauthn', (dom) => { dom.disabled = false });
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const svg = `<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background:new 0 0 216 216" viewBox="0 0 216 216" class="wwa-table-svg"><style>.st2{fill-rule:evenodd;clip-rule:evenodd;fill:#818286}</style><g id="Isolation_Mode"><path d="M0 0h216v216H0z" style="fill:none"/><path d="M172.32 96.79c0 13.78-8.48 25.5-20.29 29.78l7.14 11.83-10.57 13 10.57 12.71-17.04 22.87-12.01-12.82V125.7c-10.68-4.85-18.15-15.97-18.15-28.91 0-17.4 13.51-31.51 30.18-31.51 16.66 0 30.17 14.11 30.17 31.51zm-30.18 4.82c4.02 0 7.28-3.4 7.28-7.6 0-4.2-3.26-7.61-7.28-7.61s-7.28 3.4-7.28 7.61c-.01 4.2 3.26 7.6 7.28 7.6z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#a2a1a3"/><path d="M172.41 96.88c0 13.62-8.25 25.23-19.83 29.67l6.58 11.84-9.73 13 9.73 12.71-17.03 23.05v-85.54c4.02 0 7.28-3.41 7.28-7.6 0-4.2-3.26-7.61-7.28-7.61V65.28c16.73 0 30.28 14.15 30.28 31.6zM120.24 131.43c-9.75-8-16.3-20.3-17.2-34.27H50.8c-10.96 0-19.84 9.01-19.84 20.13v25.17c0 5.56 4.44 10.07 9.92 10.07h69.44c5.48 0 9.92-4.51 9.92-10.07v-11.03z" class="st2"/><path d="M73.16 91.13c-2.42-.46-4.82-.89-7.11-1.86-8.65-3.63-13.69-10.32-15.32-19.77-1.12-6.47-.59-12.87 2.03-18.92 3.72-8.6 10.39-13.26 19.15-14.84 5.24-.94 10.46-.73 15.5 1.15 7.59 2.82 12.68 8.26 15.03 16.24 2.38 8.05 2.03 16.1-1.56 23.72-3.72 7.96-10.21 12.23-18.42 13.9-.68.14-1.37.27-2.05.41-2.41-.03-4.83-.03-7.25-.03z" style="fill:#818286"/></g></svg>`;
|
||||
|
||||
// Whether the broswer supports WebAuthn
|
||||
if (window.PublicKeyCredential === undefined || navigator.credentials.create === undefined || typeof navigator.credentials.create !== 'function') {
|
||||
jQuery('#wwa-bind, #wwa-test').attr('disabled', 'disabled');
|
||||
@ -24,12 +26,13 @@ function updateList() {
|
||||
type: 'GET',
|
||||
data: {
|
||||
action: 'wwa_authenticator_list',
|
||||
user_id: php_vars.user_id
|
||||
user_id: php_vars.user_id,
|
||||
_ajax_nonce: php_vars._ajax_nonce
|
||||
},
|
||||
success: function (data) {
|
||||
if (typeof data === 'string') {
|
||||
console.warn(data);
|
||||
jQuery('#wwa-authenticator-list').html(`<tr><td colspan="${jQuery('.wwa-usernameless-th').css('display') === 'none' ? '5' : '6'}">${php_vars.i18n_8}</td></tr>`);
|
||||
jQuery('#wwa-authenticator-list').html(`<tr><td colspan="${getColspan()}">${php_vars.i18n_8}</td></tr>`);
|
||||
return;
|
||||
}
|
||||
if (data.length === 0) {
|
||||
@ -38,7 +41,12 @@ function updateList() {
|
||||
} else {
|
||||
jQuery('.wwa-usernameless-th, .wwa-usernameless-td').hide();
|
||||
}
|
||||
jQuery('#wwa-authenticator-list').html(`<tr><td colspan="${jQuery('.wwa-usernameless-th').css('display') === 'none' ? '5' : '6'}">${php_vars.i18n_17}</td></tr>`);
|
||||
if (configs.show_authenticator_type === 'true') {
|
||||
jQuery('.wwa-type-th, .wwa-type-td').show();
|
||||
} else {
|
||||
jQuery('.wwa-type-th, .wwa-type-td').hide();
|
||||
}
|
||||
jQuery('#wwa-authenticator-list').html(`<tr><td colspan="${getColspan()}">${php_vars.i18n_17}</td></tr>`);
|
||||
jQuery('#wwa_usernameless_tip').text('');
|
||||
jQuery('#wwa_usernameless_tip').hide();
|
||||
jQuery('#wwa_type_tip').text('');
|
||||
@ -59,7 +67,7 @@ function updateList() {
|
||||
item_type_disabled = true;
|
||||
}
|
||||
}
|
||||
htmlStr += `<tr><td>${item.name}</td><td>${item.type === 'none' ? php_vars.i18n_9 : (item.type === 'platform' ? php_vars.i18n_10 : php_vars.i18n_11)}${item_type_disabled ? php_vars.i18n_29 : ''}</td><td>${item.added}</td><td>${item.last_used}</td><td class="wwa-usernameless-td">${item.usernameless ? php_vars.i18n_24 + (configs.usernameless === 'true' ? '' : php_vars.i18n_26) : php_vars.i18n_25}</td><td id="${item.key}"><a href="javascript:renameAuthenticator('${item.key}', '${item.name.replaceAll('\'', '\\\'').replaceAll(''', '\\'').replaceAll('"', '\\"')}')">${php_vars.i18n_20}</a> | <a href="javascript:removeAuthenticator('${item.key}', '${item.name.replaceAll('\'', '\\\'').replaceAll(''', '\\'').replaceAll('"', '\\"')}')">${php_vars.i18n_12}</a></td></tr>`;
|
||||
htmlStr += `<tr><td>${svg}${item.name}</td>${configs.show_authenticator_type === 'true' ? `<td class="wwa-type-td">${item.type === 'none' ? php_vars.i18n_9 : (item.type === 'platform' ? php_vars.i18n_10 : php_vars.i18n_11)}${item_type_disabled ? php_vars.i18n_29 : ''}</td>` : ''}<td>${item.added}</td><td>${item.last_used}</td><td class="wwa-usernameless-td">${item.usernameless ? php_vars.i18n_24 + (configs.usernameless === 'true' ? '' : php_vars.i18n_26) : php_vars.i18n_25}</td><td id="${item.key}"><a href="javascript:renameAuthenticator('${item.key}', '${item.name.replaceAll('\'', '\\\'').replaceAll(''', '\\'').replaceAll('"', '\\"')}')">${php_vars.i18n_20}</a> | <a href="javascript:removeAuthenticator('${item.key}', '${item.name.replaceAll('\'', '\\\'').replaceAll(''', '\\'').replaceAll('"', '\\"')}')">${php_vars.i18n_12}</a></td></tr>`;
|
||||
}
|
||||
jQuery('#wwa-authenticator-list').html(htmlStr);
|
||||
if (has_usernameless || configs.usernameless === 'true') {
|
||||
@ -67,6 +75,11 @@ function updateList() {
|
||||
} else {
|
||||
jQuery('.wwa-usernameless-th, .wwa-usernameless-td').hide();
|
||||
}
|
||||
if (configs.show_authenticator_type === 'true') {
|
||||
jQuery('.wwa-type-th, .wwa-type-td').show();
|
||||
} else {
|
||||
jQuery('.wwa-type-th, .wwa-type-td').hide();
|
||||
}
|
||||
if (has_usernameless && configs.usernameless !== 'true') {
|
||||
jQuery('#wwa_usernameless_tip').text(php_vars.i18n_27);
|
||||
jQuery('#wwa_usernameless_tip').show();
|
||||
@ -87,11 +100,23 @@ function updateList() {
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
jQuery('#wwa-authenticator-list').html(`<tr><td colspan="${jQuery('.wwa-usernameless-th').css('display') === 'none' ? '5' : '6'}">${php_vars.i18n_8}</td></tr>`);
|
||||
jQuery('#wwa-authenticator-list').html(`<tr><td colspan="${getColspan()}">${php_vars.i18n_8}</td></tr>`);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Compute current number of visible columns for colspan
|
||||
function getColspan() {
|
||||
let cols = 4; // Identifier, Registered, Last used, Action
|
||||
if (jQuery('.wwa-type-th').length > 0 && jQuery('.wwa-type-th').css('display') !== 'none') {
|
||||
cols++;
|
||||
}
|
||||
if (jQuery('.wwa-usernameless-th').length > 0 && jQuery('.wwa-usernameless-th').css('display') !== 'none') {
|
||||
cols++;
|
||||
}
|
||||
return cols;
|
||||
}
|
||||
|
||||
/** Code Base64URL into Base64
|
||||
*
|
||||
* @param {string} input Base64URL coded string
|
||||
@ -140,6 +165,10 @@ jQuery('.wwa-cancel').click((e) => {
|
||||
jQuery('#wwa-verify-block').hide();
|
||||
})
|
||||
|
||||
// Prevent WebAuthn registration fields from triggering WordPress's unsaved changes dialog.
|
||||
// The form="wwa-registration" attribute on these inputs disassociates them from #your-profile,
|
||||
// so they are excluded from jQuery serialize() comparisons in user-profile.js.
|
||||
|
||||
jQuery('#wwa_authenticator_name').keydown((e) => {
|
||||
if (e.keyCode === 13) {
|
||||
jQuery('#wwa-bind').trigger('click');
|
||||
@ -160,16 +189,19 @@ jQuery('#wwa-bind').click((e) => {
|
||||
jQuery('#wwa-bind').attr('disabled', 'disabled');
|
||||
jQuery('#wwa_authenticator_name').attr('disabled', 'disabled');
|
||||
jQuery('.wwa_authenticator_usernameless').attr('disabled', 'disabled');
|
||||
jQuery('#wwa_authenticator_type').attr('disabled', 'disabled');
|
||||
if (configs.show_authenticator_type === 'true') {
|
||||
jQuery('#wwa_authenticator_type').attr('disabled', 'disabled');
|
||||
}
|
||||
jQuery.ajax({
|
||||
url: php_vars.ajax_url,
|
||||
type: 'GET',
|
||||
data: {
|
||||
action: 'wwa_create',
|
||||
name: jQuery('#wwa_authenticator_name').val(),
|
||||
type: jQuery('#wwa_authenticator_type').val(),
|
||||
type: configs.show_authenticator_type === 'true' ? jQuery('#wwa_authenticator_type').val() : (configs.allow_authenticator_type !== 'none' ? configs.allow_authenticator_type : 'none'),
|
||||
usernameless: jQuery('.wwa_authenticator_usernameless:checked').val() ? jQuery('.wwa_authenticator_usernameless:checked').val() : 'false',
|
||||
user_id: php_vars.user_id
|
||||
user_id: php_vars.user_id,
|
||||
_ajax_nonce: php_vars._ajax_nonce
|
||||
},
|
||||
success: function (data) {
|
||||
if (typeof data === 'string') {
|
||||
@ -178,7 +210,9 @@ jQuery('#wwa-bind').click((e) => {
|
||||
jQuery('#wwa-bind').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_name').removeAttr('disabled');
|
||||
jQuery('.wwa_authenticator_usernameless').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
if (configs.show_authenticator_type === 'true') {
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
}
|
||||
updateList();
|
||||
return;
|
||||
}
|
||||
@ -241,10 +275,11 @@ jQuery('#wwa-bind').click((e) => {
|
||||
data: {
|
||||
data: window.btoa(AuthenticatorAttestationResponse),
|
||||
name: jQuery('#wwa_authenticator_name').val(),
|
||||
type: jQuery('#wwa_authenticator_type').val(),
|
||||
type: configs.show_authenticator_type === 'true' ? jQuery('#wwa_authenticator_type').val() : (configs.allow_authenticator_type !== 'none' ? configs.allow_authenticator_type : 'none'),
|
||||
usernameless: jQuery('.wwa_authenticator_usernameless:checked').val() ? jQuery('.wwa_authenticator_usernameless:checked').val() : 'false',
|
||||
clientid: clientID,
|
||||
user_id: php_vars.user_id
|
||||
user_id: php_vars.user_id,
|
||||
_ajax_nonce: php_vars._ajax_nonce
|
||||
},
|
||||
success: function (data) {
|
||||
if (data.trim() === 'true') {
|
||||
@ -254,7 +289,9 @@ jQuery('#wwa-bind').click((e) => {
|
||||
jQuery('#wwa_authenticator_name').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_name').val('');
|
||||
jQuery('.wwa_authenticator_usernameless').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
if (configs.show_authenticator_type === 'true') {
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
}
|
||||
updateList();
|
||||
} else {
|
||||
// Register failed
|
||||
@ -262,7 +299,9 @@ jQuery('#wwa-bind').click((e) => {
|
||||
jQuery('#wwa-bind').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_name').removeAttr('disabled');
|
||||
jQuery('.wwa_authenticator_usernameless').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
if (configs.show_authenticator_type === 'true') {
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
}
|
||||
updateList();
|
||||
}
|
||||
},
|
||||
@ -271,7 +310,9 @@ jQuery('#wwa-bind').click((e) => {
|
||||
jQuery('#wwa-bind').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_name').removeAttr('disabled');
|
||||
jQuery('.wwa_authenticator_usernameless').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
if (configs.show_authenticator_type === 'true') {
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
}
|
||||
updateList();
|
||||
}
|
||||
})
|
||||
@ -282,7 +323,9 @@ jQuery('#wwa-bind').click((e) => {
|
||||
jQuery('#wwa-bind').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_name').removeAttr('disabled');
|
||||
jQuery('.wwa_authenticator_usernameless').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
if (configs.show_authenticator_type === 'true') {
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
}
|
||||
updateList();
|
||||
})
|
||||
},
|
||||
@ -291,7 +334,9 @@ jQuery('#wwa-bind').click((e) => {
|
||||
jQuery('#wwa-bind').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_name').removeAttr('disabled');
|
||||
jQuery('.wwa_authenticator_usernameless').removeAttr('disabled');
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
if (configs.show_authenticator_type === 'true') {
|
||||
jQuery('#wwa_authenticator_type').removeAttr('disabled');
|
||||
}
|
||||
updateList();
|
||||
}
|
||||
})
|
||||
@ -428,7 +473,8 @@ function renameAuthenticator(id, name) {
|
||||
id: id,
|
||||
name: new_name,
|
||||
target: 'rename',
|
||||
user_id: php_vars.user_id
|
||||
user_id: php_vars.user_id,
|
||||
_ajax_nonce: php_vars._ajax_nonce
|
||||
},
|
||||
success: function () {
|
||||
updateList();
|
||||
@ -456,7 +502,8 @@ function removeAuthenticator(id, name) {
|
||||
action: 'wwa_modify_authenticator',
|
||||
id: id,
|
||||
target: 'remove',
|
||||
user_id: php_vars.user_id
|
||||
user_id: php_vars.user_id,
|
||||
_ajax_nonce: php_vars._ajax_nonce
|
||||
},
|
||||
success: function () {
|
||||
updateList();
|
||||
|
||||
Reference in New Issue
Block a user