Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions build/media_source/plg_system_webauthn/js/login.es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,8 @@ window.Joomla = window.Joomla || {};
* internal page which handles the login server-side.
*
* @param { Object} publicKey Public key request options, returned from the server
* @param {String} callbackUrl The URL we will use to post back to the server. Must include
* the anti-CSRF token.
*/
const handleLoginChallenge = (publicKey, callbackUrl) => {
const handleLoginChallenge = (publicKey) => {
const arrayToBase64String = (a) => btoa(String.fromCharCode(...a));

const base64url2base64 = (input) => {
Expand Down Expand Up @@ -172,7 +170,8 @@ window.Joomla = window.Joomla || {};
};

// Send the response to your server
window.location = `${callbackUrl}&option=com_ajax&group=system&plugin=webauthn&`
const paths = Joomla.getOptions('system.paths');
window.location = `${paths ? `${paths.base}/index.php` : window.location.pathname}?${Joomla.getOptions('csrf.token')}=1&option=com_ajax&group=system&plugin=webauthn&`
+ `format=raw&akaction=login&encoding=redirect&data=${
btoa(JSON.stringify(publicKeyCredential))}`;
})
Expand All @@ -187,13 +186,11 @@ window.Joomla = window.Joomla || {};
* for the user.
*
* @param {string} formId The login form's or login module's HTML ID
* @param {string} callbackUrl The URL we will use to post back to the server. Must include
* the anti-CSRF token.
*
* @returns {boolean} Always FALSE to prevent BUTTON elements from reloading the page.
*/
// eslint-disable-next-line no-unused-vars
Joomla.plgSystemWebauthnLogin = (formId, callbackUrl) => {
Joomla.plgSystemWebauthnLogin = (formId) => {
// Get the username
const elFormContainer = document.getElementById(formId);
const elUsername = lookForField(elFormContainer, 'input[name=username]');
Expand Down Expand Up @@ -226,9 +223,14 @@ window.Joomla = window.Joomla || {};
username,
returnUrl,
};
postBackData[Joomla.getOptions('csrf.token')] = 1;

const paths = Joomla.getOptions('system.paths');

Joomla.request({
url: callbackUrl,
url: `${paths ? `${paths.base}/index.php` : window.location.pathname}?${Joomla.getOptions(
'csrf.token',
)}=1`,
method: 'POST',
data: interpolateParameters(postBackData),
onSuccess(rawResponse) {
Expand All @@ -243,7 +245,7 @@ window.Joomla = window.Joomla || {};
*/
}

handleLoginChallenge(jsonData, callbackUrl);
handleLoginChallenge(jsonData);
},
onError: (xhr) => {
handleLoginError(`${xhr.status} ${xhr.statusText}`);
Expand All @@ -258,7 +260,7 @@ window.Joomla = window.Joomla || {};
if (loginButtons.length) {
loginButtons.forEach((button) => {
button.addEventListener('click', ({ currentTarget }) => {
Joomla.plgSystemWebauthnLogin(currentTarget.getAttribute('data-webauthn-form'), currentTarget.getAttribute('data-webauthn-url'));
Joomla.plgSystemWebauthnLogin(currentTarget.getAttribute('data-webauthn-form'));
});
});
}
Expand Down
14 changes: 10 additions & 4 deletions build/media_source/plg_system_webauthn/js/management.es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ window.Joomla = window.Joomla || {};
}

const publicKey = JSON.parse(atob(elStore.dataset.public_key));
const postURL = atob(elStore.dataset.postback_url);
const paths = Joomla.getOptions('system.paths');
const postURL = `${paths ? `${paths.base}/index.php` : window.location.pathname}`;

const arrayToBase64String = (a) => btoa(String.fromCharCode(...a));

Expand Down Expand Up @@ -137,6 +138,7 @@ window.Joomla = window.Joomla || {};
encoding: 'raw',
data: btoa(JSON.stringify(publicKeyCredential)),
};
postBackData[Joomla.getOptions('csrf.token')] = 1;

Joomla.request({
url: postURL,
Expand Down Expand Up @@ -183,12 +185,13 @@ window.Joomla = window.Joomla || {};
return false;
}

const postURL = atob(elStore.dataset.postback_url);
const paths = Joomla.getOptions('system.paths');
const postURL = `${paths ? `${paths.base}/index.php` : window.location.pathname}`;

// Find the UI elements
const elTR = that.parentElement.parentElement;
const credentialId = elTR.dataset.credential_id;
const elTDs = elTR.querySelectorAll('td');
const elTDs = elTR.querySelectorAll('.webauthnManagementCell');
const elLabelTD = elTDs[0];
const elButtonsTD = elTDs[1];
const elButtons = elButtonsTD.querySelectorAll('button');
Expand Down Expand Up @@ -220,6 +223,7 @@ window.Joomla = window.Joomla || {};
credential_id: credentialId,
new_label: elNewLabel,
};
postBackData[Joomla.getOptions('csrf.token')] = 1;

Joomla.request({
url: postURL,
Expand Down Expand Up @@ -293,7 +297,8 @@ window.Joomla = window.Joomla || {};
return false;
}

const postURL = atob(elStore.dataset.postback_url);
const paths = Joomla.getOptions('system.paths');
const postURL = `${paths ? `${paths.base}/index.php` : window.location.pathname}`;

// Find the UI elements
const elTR = that.parentElement.parentElement;
Expand All @@ -317,6 +322,7 @@ window.Joomla = window.Joomla || {};
akaction: 'delete',
credential_id: credentialId,
};
postBackData[Joomla.getOptions('csrf.token')] = 1;

Joomla.request({
url: postURL,
Expand Down
12 changes: 5 additions & 7 deletions layouts/plugins/system/webauthn/manage.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\FileLayout;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\User\User;
use Joomla\CMS\User\UserHelper;
use Joomla\Plugin\System\Webauthn\Helper\CredentialsCreation;
use Joomla\Plugin\System\Webauthn\Authentication;
use Joomla\Plugin\System\Webauthn\Helper\Joomla;

/**
Expand Down Expand Up @@ -79,15 +78,14 @@
* that problem.
*/
$randomId = 'plg_system_webauthn_' . UserHelper::genRandomPassword(32);
/** @noinspection PhpInternalEntityUsedInspection */
// phpcs:ignore
$publicKey = $allow_add ? base64_encode(CredentialsCreation::createPublicKey($user)) : '{}';
$postbackURL = base64_encode(rtrim(Uri::base(), '/') . '/index.php?' . Joomla::getToken() . '=1');
$publicKey = $allow_add ? base64_encode(json_encode(Authentication::getPubKeyCreationOptions($user))) : '{}';

?>
<div class="plg_system_webauthn" id="plg_system_webauthn-management-interface">
<span id="<?php echo $randomId ?>"
data-public_key="<?php echo $publicKey ?>"
data-postback_url="<?php echo $postbackURL ?>"
></span>

<?php // phpcs:ignore
Expand All @@ -111,8 +109,8 @@
<?php // phpcs:ignore
foreach ($credentials as $method): ?>
<tr data-credential_id="<?php echo $method['id'] ?>">
<th scope="row"><?php echo htmlentities($method['label']) ?></th>
<td>
<th scope="row" class="webauthnManagementCell"><?php echo htmlentities($method['label']) ?></th>
<td class="webauthnManagementCell">
<button data-random-id="<?php echo $randomId; ?>" class="plg_system_webauthn-manage-edit btn btn-secondary">
<span class="icon-edit" aria-hidden="true"></span>
<?php echo Text::_('PLG_SYSTEM_WEBAUTHN_MANAGE_BTN_EDIT_LABEL') ?>
Expand Down
41 changes: 41 additions & 0 deletions plugins/system/webauthn/services/provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
/**
* @package Joomla.Plugin
* @subpackage System.Webauthn
*
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

defined('_JEXEC') || die;

use Joomla\CMS\Extension\PluginInterface;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use Joomla\Event\DispatcherInterface;
use Joomla\Plugin\System\Webauthn\Extension\Webauthn;

return new class implements ServiceProviderInterface {
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 7.0.0
*/
public function register(Container $container)
{
$container->set(
PluginInterface::class,
function (Container $container) {
$config = (array) PluginHelper::getPlugin('system', 'webauthn');
$subject = $container->get(DispatcherInterface::class);

return new Webauthn($subject, $config);
}
);
}
};
Loading