mirror of
https://github.com/joomla/joomla-cms.git
synced 2024-06-16 09:02:52 +00:00
Fix/38233 webauth preload fido (#38664)
* Use cached FIDO metadata Places a copy of fido.jwt in the plugin's directory * Use cached FIDO metadata Use the cached FIDO metadata in the plugin * Use cached FIDO metadata Remove unused local file fallback * Use cached FIDO metadata Simplify * Use cached FIDO metadata Update Joomla build script * Use cached FIDO metadata Let's not break the build if the FIDO server is down * Use cached FIDO metadata Do not include the fido.jwt in the repo * Use cached FIDO metadata Make sure not to re-fetch the fido.jwt file if it already exists. * Use cached FIDO metadata Move the check for the fido.jwt file right after composer install, do not try to fetch the file twice * Use cached FIDO metadata Update lang string * Use cached FIDO metadata Set the attestation support to disabled by default * Update deleted files to PR #38664 Co-authored-by: Richard Fath <richard67@users.noreply.github.com>
This commit is contained in:
parent
1c4fcf60b6
commit
205c7a5f7f
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -101,3 +101,6 @@ RoboFile.ini
|
|||
# Media Manager
|
||||
/media/com_media/js/mediamanager.min.js.map
|
||||
/media/com_media/css/mediamanager.min.css.map
|
||||
|
||||
# WebAuthn FIDO metadata cache
|
||||
/plugins/system/webauthn/fido.jwt
|
||||
|
|
|
@ -6450,6 +6450,8 @@ class JoomlaInstallerScript
|
|||
'/media/vendor/hotkeys.js/js/hotkeys.min.js',
|
||||
'/media/vendor/hotkeys.js/js/hotkeys.min.js.gz',
|
||||
'/media/vendor/hotkeys.js/LICENSE',
|
||||
// From 4.2.1 to 4.2.2
|
||||
'/administrator/cache/fido.jwt',
|
||||
);
|
||||
|
||||
$folders = array(
|
||||
|
|
|
@ -24,7 +24,7 @@ PLG_SYSTEM_WEBAUTHN_ERR_NO_BROWSER_SUPPORT="Sorry, your browser does not support
|
|||
PLG_SYSTEM_WEBAUTHN_ERR_NO_STORED_CREDENTIAL="Cannot find the stored credentials for your login authenticator."
|
||||
PLG_SYSTEM_WEBAUTHN_ERR_USER_REMOVED="The user for this authenticator seems to no longer exist on this site."
|
||||
PLG_SYSTEM_WEBAUTHN_ERR_XHR_INITCREATE="Cannot get the authenticator registration information from your site."
|
||||
PLG_SYSTEM_WEBAUTHN_FIELD_ATTESTATION_SUPPORT_DESC="Only allow authenticators with verifiable cryptographic signatures to be used for WebAuthn logins. Strongly recommended for high security environments. Requires your site to be able to access <code>https://mds.fidoalliance.org/</code> directly, a writeable cache directory, the system temporary directory being writeable by PHP, and the OpenSSL extension. May prevent some cheaper, non-certified authenticators from working at all. Disabling it also prevents Joomla from identifying the make and model of the authenticator you are using (no icon will be displayed next to the Authenticator Name).<br/><strong>Pro tip:</strong> If you are behind a firewall you can place the data downloaded from <a href=\"https://mds.fidoalliance.org/\" target=\"_blank\" rel=\"noopener noreferrer\">the FIDO Alliance</a> into the file <code>administrator/cache/fido.jwt</code> for this feature to work properly."
|
||||
PLG_SYSTEM_WEBAUTHN_FIELD_ATTESTATION_SUPPORT_DESC="Only allow authenticators with verifiable cryptographic signatures to be used for WebAuthn logins. Strongly recommended for high security environments. Requires the system temporary directory being writeable by PHP, and the OpenSSL extension. May prevent some cheaper, non-certified authenticators from working at all. Disabling it also prevents Joomla from identifying the make and model of the authenticator you are using (no icon will be displayed next to the Authenticator Name)."
|
||||
PLG_SYSTEM_WEBAUTHN_FIELD_ATTESTATION_SUPPORT_LABEL="Attestation Support"
|
||||
PLG_SYSTEM_WEBAUTHN_FIELD_DESC="Lets you manage passwordless login methods using the W3C Web Authentication standard. You need a supported browser and authenticator (eg Google Chrome or Firefox with a FIDO2 certified security key).<br><br><strong>MacOS/iOS/watchOS:</strong> Touch/Face ID.<br><strong>Windows:</strong> Hello (Fingerprint / Facial Recognition / PIN).<br><strong>Android:</strong> Biometric screen lock.<br><br>You can find more details in the <a href=\"https://docs.joomla.org/Special:MyLanguage/WebAuthn_Passwordless_Login\" target=\"_blank\" rel=\"noopener noreferrer\">WebAuthn Passwordless Login documentation</a>."
|
||||
PLG_SYSTEM_WEBAUTHN_FIELD_LABEL="W3C Web Authentication (WebAuthn) Login"
|
||||
|
|
|
@ -270,6 +270,14 @@ if ($composerReturnCode !== 0) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
// Try to update the fido.jwt file
|
||||
if (!file_exists(rtrim($fullpath, '\\/') . '/plugins/system/webauthn/fido.jwt'))
|
||||
{
|
||||
echo "The file plugins/system/webauthn/fido.jwt was not created. Build failed.\n";
|
||||
|
||||
exit (1);
|
||||
}
|
||||
|
||||
system('npm install --unsafe-perm', $npmReturnCode);
|
||||
|
||||
if ($npmReturnCode !== 0) {
|
||||
|
|
55
build/update_fido_cache.php
Normal file
55
build/update_fido_cache.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Build
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* @phpcs :disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
*/
|
||||
|
||||
echo <<< TEXT
|
||||
Update FIDO Cache version 1.0
|
||||
|
||||
Distributed under the GNU General Public License version 2, or at your option
|
||||
any later version published by the Free Software Foundation.
|
||||
|
||||
TEXT;
|
||||
|
||||
if (!isset($fullPath))
|
||||
{
|
||||
$fullPath = dirname(__DIR__);
|
||||
}
|
||||
|
||||
$filePath = rtrim($fullPath, '\\/') . '/plugins/system/webauthn/fido.jwt';
|
||||
|
||||
if (is_file($filePath) && filemtime($filePath) > (time() - 864000))
|
||||
{
|
||||
echo "The file $filePath already exists and is current; nothing to do.\n";
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
echo "Fetching FIDO metadata statements...\n";
|
||||
|
||||
$context = stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'GET',
|
||||
'follow_location' => 1,
|
||||
'timeout' => 5.0,
|
||||
]
|
||||
]);
|
||||
|
||||
$rawJwt = @file_get_contents('https://mds.fidoalliance.org/', false, $context);
|
||||
|
||||
if ($rawJwt === false) {
|
||||
echo "Could not get an updated fido.jwt file.\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
echo "Saving JWT file in the plugin directory...\n";
|
||||
|
||||
file_put_contents($filePath, $rawJwt);
|
||||
|
||||
echo "File saved: $filePath\n";
|
|
@ -117,5 +117,10 @@
|
|||
},
|
||||
"replace": {
|
||||
"paragonie/random_compat": "9.99.99"
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": [
|
||||
"php build/update_fido_cache.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ return new class implements ServiceProviderInterface
|
|||
$metadataRepository = null;
|
||||
$params = new Joomla\Registry\Registry($config['params'] ?? '{}');
|
||||
|
||||
if ($params->get('attestationSupport', 1) == 1) {
|
||||
if ($params->get('attestationSupport', 0) == 1) {
|
||||
$metadataRepository = $container->has(MetadataStatementRepository::class)
|
||||
? $container->get(MetadataStatementRepository::class)
|
||||
: new MetadataRepository();
|
||||
|
|
|
@ -133,7 +133,7 @@ final class Webauthn extends CMSPlugin implements SubscriberInterface
|
|||
], $logLevels, ["webauthn.system"]);
|
||||
|
||||
$this->authenticationHelper = $authHelper ?? (new Authentication());
|
||||
$this->authenticationHelper->setAttestationSupport($this->params->get('attestationSupport', 1) == 1);
|
||||
$this->authenticationHelper->setAttestationSupport($this->params->get('attestationSupport', 0) == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -52,14 +52,12 @@ final class MetadataRepository implements MetadataStatementRepository
|
|||
private $mdsMap = [];
|
||||
|
||||
/**
|
||||
* Public constructor.
|
||||
* Have I already tried to load the metadata cache?
|
||||
*
|
||||
* @since 4.2.0
|
||||
* @var bool
|
||||
* @since __DEPLOY_VERSION__
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->load();
|
||||
}
|
||||
private $loaded = false;
|
||||
|
||||
/**
|
||||
* Find an authenticator metadata statement given an AAGUID
|
||||
|
@ -71,6 +69,8 @@ final class MetadataRepository implements MetadataStatementRepository
|
|||
*/
|
||||
public function findOneByAAGUID(string $aaguid): ?MetadataStatement
|
||||
{
|
||||
$this->load();
|
||||
|
||||
$idx = $this->mdsMap[$aaguid] ?? null;
|
||||
|
||||
return $idx ? $this->mdsCache[$idx] : null;
|
||||
|
@ -84,6 +84,8 @@ final class MetadataRepository implements MetadataStatementRepository
|
|||
*/
|
||||
public function getKnownAuthenticators(): array
|
||||
{
|
||||
$this->load();
|
||||
|
||||
$mapKeys = function (MetadataStatement $meta) {
|
||||
return $meta->getAaguid();
|
||||
};
|
||||
|
@ -107,56 +109,22 @@ final class MetadataRepository implements MetadataStatementRepository
|
|||
/**
|
||||
* Load the authenticator metadata cache
|
||||
*
|
||||
* @param bool $force Force reload from the web service
|
||||
*
|
||||
* @return void
|
||||
* @since 4.2.0
|
||||
*/
|
||||
private function load(bool $force = false): void
|
||||
private function load(): void
|
||||
{
|
||||
if ($this->loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->loaded = true;
|
||||
|
||||
$this->mdsCache = [];
|
||||
$this->mdsMap = [];
|
||||
$jwtFilename = JPATH_CACHE . '/fido.jwt';
|
||||
|
||||
// If the file exists and it's over one month old do retry loading it.
|
||||
if (file_exists($jwtFilename) && filemtime($jwtFilename) < (time() - 2592000)) {
|
||||
$force = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to load the MDS source from the FIDO Alliance and cache it.
|
||||
*
|
||||
* We use a short timeout limit to avoid delaying the page load for way too long. If we fail
|
||||
* to download the file in a reasonable amount of time we write an empty string in the
|
||||
* file which causes this method to not proceed any further.
|
||||
*/
|
||||
if (!file_exists($jwtFilename) || $force) {
|
||||
// Only try to download anything if we can actually cache it!
|
||||
if ((file_exists($jwtFilename) && is_writable($jwtFilename)) || (!file_exists($jwtFilename) && is_writable(JPATH_CACHE))) {
|
||||
$http = HttpFactory::getHttp();
|
||||
try {
|
||||
$response = $http->get('https://mds.fidoalliance.org/', [], 5);
|
||||
$content = ($response->code < 200 || $response->code > 299) ? '' : $response->body;
|
||||
} catch (\Throwable $e) {
|
||||
$content = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we could not download anything BUT a non-empty file already exists we must NOT
|
||||
* overwrite it.
|
||||
*
|
||||
* This allows, for example, the site owner to manually place the FIDO MDS cache file
|
||||
* in administrator/cache/fido.jwt. This would be useful for high security sites which
|
||||
* require attestation BUT are behind a firewall (or disconnected from the Internet),
|
||||
* therefore cannot download the MDS cache!
|
||||
*/
|
||||
if (!empty($content) || !file_exists($jwtFilename) || filesize($jwtFilename) <= 1024) {
|
||||
file_put_contents($jwtFilename, $content);
|
||||
}
|
||||
}
|
||||
|
||||
$rawJwt = file_get_contents($jwtFilename);
|
||||
$jwtFilename = JPATH_PLUGINS . '/system/webauthn/fido.jwt';
|
||||
$rawJwt = file_get_contents($jwtFilename);
|
||||
|
||||
if (!is_string($rawJwt) || strlen($rawJwt) < 1024) {
|
||||
return;
|
||||
|
@ -175,19 +143,6 @@ final class MetadataRepository implements MetadataStatementRepository
|
|||
|
||||
unset($rawJwt);
|
||||
|
||||
// Do I need to forcibly update the cache? The JWT has the nextUpdate claim to tell us when to do that.
|
||||
try {
|
||||
$nextUpdate = new Date($token->claims()->get('nextUpdate', '2020-01-01'));
|
||||
|
||||
if (!$force && !$nextUpdate->diff(new Date())->invert) {
|
||||
$this->load(true);
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// OK, don't worry if don't know when the next update is.
|
||||
}
|
||||
|
||||
$entriesMapper = function (object $entry) {
|
||||
try {
|
||||
$array = json_decode(json_encode($entry->metadataStatement), true);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
label="PLG_SYSTEM_WEBAUTHN_FIELD_ATTESTATION_SUPPORT_LABEL"
|
||||
description="PLG_SYSTEM_WEBAUTHN_FIELD_ATTESTATION_SUPPORT_DESC"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
default="0"
|
||||
filter="integer"
|
||||
>
|
||||
<option value="0">JDISABLED</option>
|
||||
|
|
Loading…
Reference in New Issue
Block a user