Update website
This commit is contained in:
parent
0a686aeb9a
commit
c4ffa0f6ee
4360 changed files with 1727 additions and 718385 deletions
|
@ -1,149 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Second authentication factor handling
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Plugins\TwoFactor;
|
||||
|
||||
use PhpMyAdmin\Plugins\TwoFactorPlugin;
|
||||
use PhpMyAdmin\TwoFactor;
|
||||
use PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException;
|
||||
use PragmaRX\Google2FA\Exceptions\InvalidCharactersException;
|
||||
use PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException;
|
||||
use PragmaRX\Google2FAQRCode\Google2FA;
|
||||
|
||||
use function __;
|
||||
use function extension_loaded;
|
||||
|
||||
/**
|
||||
* HOTP and TOTP based two-factor authentication
|
||||
*
|
||||
* Also known as Google, Authy, or OTP
|
||||
*/
|
||||
class Application extends TwoFactorPlugin
|
||||
{
|
||||
/** @var string */
|
||||
public static $id = 'application';
|
||||
|
||||
/** @var Google2FA */
|
||||
protected $google2fa;
|
||||
|
||||
/**
|
||||
* Creates object
|
||||
*
|
||||
* @param TwoFactor $twofactor TwoFactor instance
|
||||
*/
|
||||
public function __construct(TwoFactor $twofactor)
|
||||
{
|
||||
parent::__construct($twofactor);
|
||||
$this->google2fa = new Google2FA();
|
||||
$this->google2fa->setWindow(8);
|
||||
if (isset($this->twofactor->config['settings']['secret'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->twofactor->config['settings']['secret'] = '';
|
||||
}
|
||||
|
||||
public function getGoogle2fa(): Google2FA
|
||||
{
|
||||
return $this->google2fa;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks authentication, returns true on success
|
||||
*
|
||||
* @throws IncompatibleWithGoogleAuthenticatorException
|
||||
* @throws InvalidCharactersException
|
||||
* @throws SecretKeyTooShortException
|
||||
*/
|
||||
public function check(): bool
|
||||
{
|
||||
$this->provided = false;
|
||||
if (! isset($_POST['2fa_code'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->provided = true;
|
||||
|
||||
return (bool) $this->google2fa->verifyKey($this->twofactor->config['settings']['secret'], $_POST['2fa_code']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders user interface to enter two-factor authentication
|
||||
*
|
||||
* @return string HTML code
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return $this->template->render('login/twofactor/application');
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders user interface to configure two-factor authentication
|
||||
*
|
||||
* @return string HTML code
|
||||
*/
|
||||
public function setup()
|
||||
{
|
||||
$secret = $this->twofactor->config['settings']['secret'];
|
||||
$inlineUrl = $this->google2fa->getQRCodeInline(
|
||||
'phpMyAdmin (' . $this->getAppId(false) . ')',
|
||||
$this->twofactor->user,
|
||||
$secret
|
||||
);
|
||||
|
||||
return $this->template->render('login/twofactor/application_configure', [
|
||||
'image' => $inlineUrl,
|
||||
'secret' => $secret,
|
||||
'has_imagick' => extension_loaded('imagick'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs backend configuration
|
||||
*
|
||||
* @throws IncompatibleWithGoogleAuthenticatorException
|
||||
* @throws InvalidCharactersException
|
||||
* @throws SecretKeyTooShortException
|
||||
*/
|
||||
public function configure(): bool
|
||||
{
|
||||
if (! isset($_SESSION['2fa_application_key'])) {
|
||||
$_SESSION['2fa_application_key'] = $this->google2fa->generateSecretKey();
|
||||
}
|
||||
|
||||
$this->twofactor->config['settings']['secret'] = $_SESSION['2fa_application_key'];
|
||||
|
||||
$result = $this->check();
|
||||
if ($result) {
|
||||
unset($_SESSION['2fa_application_key']);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user visible name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getName()
|
||||
{
|
||||
return __('Authentication Application (2FA)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user visible description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getDescription()
|
||||
{
|
||||
return __(
|
||||
'Provides authentication using HOTP and TOTP applications such as FreeOTP, Google Authenticator or Authy.'
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Second authentication factor handling
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Plugins\TwoFactor;
|
||||
|
||||
use PhpMyAdmin\Plugins\TwoFactorPlugin;
|
||||
|
||||
/**
|
||||
* Invalid two-factor authentication showing that configured choice is not available.
|
||||
*/
|
||||
class Invalid extends TwoFactorPlugin
|
||||
{
|
||||
/** @var string */
|
||||
public static $id = 'invalid';
|
||||
|
||||
/** @var bool */
|
||||
public static $showSubmit = false;
|
||||
|
||||
/**
|
||||
* Checks authentication, returns true on success
|
||||
*/
|
||||
public function check(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders user interface to enter two-factor authentication
|
||||
*
|
||||
* @return string HTML code
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return $this->template->render('login/twofactor/invalid');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user visible name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getName()
|
||||
{
|
||||
return 'Invalid two-factor authentication';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user visible description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getDescription()
|
||||
{
|
||||
return 'Error fallback only!';
|
||||
}
|
||||
}
|
|
@ -1,220 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Second authentication factor handling
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Plugins\TwoFactor;
|
||||
|
||||
use CodeLts\U2F\U2FServer\U2FException;
|
||||
use CodeLts\U2F\U2FServer\U2FServer;
|
||||
use PhpMyAdmin\Plugins\TwoFactorPlugin;
|
||||
use PhpMyAdmin\ResponseRenderer;
|
||||
use PhpMyAdmin\TwoFactor;
|
||||
use stdClass;
|
||||
use Throwable;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Error\RuntimeError;
|
||||
use Twig\Error\SyntaxError;
|
||||
|
||||
use function __;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function json_decode;
|
||||
use function json_encode;
|
||||
|
||||
/**
|
||||
* Hardware key based two-factor authentication
|
||||
*
|
||||
* Supports FIDO U2F tokens
|
||||
*/
|
||||
class Key extends TwoFactorPlugin
|
||||
{
|
||||
/** @var string */
|
||||
public static $id = 'key';
|
||||
|
||||
/**
|
||||
* Creates object
|
||||
*
|
||||
* @param TwoFactor $twofactor TwoFactor instance
|
||||
*/
|
||||
public function __construct(TwoFactor $twofactor)
|
||||
{
|
||||
parent::__construct($twofactor);
|
||||
if (
|
||||
isset($this->twofactor->config['settings']['registrations'])
|
||||
&& is_array($this->twofactor->config['settings']['registrations'])
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->twofactor->config['settings']['registrations'] = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of U2F registration objects
|
||||
*
|
||||
* @return stdClass[]
|
||||
*/
|
||||
public function getRegistrations()
|
||||
{
|
||||
$result = [];
|
||||
foreach ($this->twofactor->config['settings']['registrations'] as $index => $data) {
|
||||
$reg = new stdClass();
|
||||
$reg->keyHandle = $data['keyHandle'];
|
||||
$reg->publicKey = $data['publicKey'];
|
||||
$reg->certificate = $data['certificate'];
|
||||
$reg->counter = $data['counter'];
|
||||
$reg->index = $index;
|
||||
$result[] = $reg;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks authentication, returns true on success
|
||||
*/
|
||||
public function check(): bool
|
||||
{
|
||||
$this->provided = false;
|
||||
if (! isset($_POST['u2f_authentication_response'], $_SESSION['authenticationRequest'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->provided = true;
|
||||
try {
|
||||
$response = json_decode($_POST['u2f_authentication_response']);
|
||||
if (! is_object($response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$auth = U2FServer::authenticate(
|
||||
$_SESSION['authenticationRequest'],
|
||||
$this->getRegistrations(),
|
||||
$response
|
||||
);
|
||||
$this->twofactor->config['settings']['registrations'][$auth->index]['counter'] = $auth->counter;
|
||||
$this->twofactor->save();
|
||||
|
||||
return true;
|
||||
} catch (U2FException $e) {
|
||||
$this->message = $e->getMessage();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads needed javascripts into the page
|
||||
*/
|
||||
public function loadScripts(): void
|
||||
{
|
||||
$response = ResponseRenderer::getInstance();
|
||||
$scripts = $response->getHeader()->getScripts();
|
||||
$scripts->addFile('vendor/u2f-api-polyfill.js');
|
||||
$scripts->addFile('u2f.js');
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders user interface to enter two-factor authentication
|
||||
*
|
||||
* @return string HTML code
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$request = U2FServer::makeAuthentication(
|
||||
$this->getRegistrations(),
|
||||
$this->getAppId(true)
|
||||
);
|
||||
$_SESSION['authenticationRequest'] = $request;
|
||||
$this->loadScripts();
|
||||
|
||||
return $this->template->render('login/twofactor/key', [
|
||||
'request' => json_encode($request),
|
||||
'is_https' => $GLOBALS['config']->isHttps(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders user interface to configure two-factor authentication
|
||||
*
|
||||
* @return string HTML code
|
||||
*
|
||||
* @throws U2FException
|
||||
* @throws Throwable
|
||||
* @throws LoaderError
|
||||
* @throws RuntimeError
|
||||
* @throws SyntaxError
|
||||
*/
|
||||
public function setup()
|
||||
{
|
||||
$registrationData = U2FServer::makeRegistration(
|
||||
$this->getAppId(true),
|
||||
$this->getRegistrations()
|
||||
);
|
||||
$_SESSION['registrationRequest'] = $registrationData['request'];
|
||||
|
||||
$this->loadScripts();
|
||||
|
||||
return $this->template->render('login/twofactor/key_configure', [
|
||||
'request' => json_encode($registrationData['request']),
|
||||
'signatures' => json_encode($registrationData['signatures']),
|
||||
'is_https' => $GLOBALS['config']->isHttps(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs backend configuration
|
||||
*/
|
||||
public function configure(): bool
|
||||
{
|
||||
$this->provided = false;
|
||||
if (! isset($_POST['u2f_registration_response'], $_SESSION['registrationRequest'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->provided = true;
|
||||
try {
|
||||
$response = json_decode($_POST['u2f_registration_response']);
|
||||
if (! is_object($response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$registration = U2FServer::register($_SESSION['registrationRequest'], $response);
|
||||
$this->twofactor->config['settings']['registrations'][] = [
|
||||
'keyHandle' => $registration->getKeyHandle(),
|
||||
'publicKey' => $registration->getPublicKey(),
|
||||
'certificate' => $registration->getCertificate(),
|
||||
'counter' => $registration->getCounter(),
|
||||
];
|
||||
|
||||
return true;
|
||||
} catch (U2FException $e) {
|
||||
$this->message = $e->getMessage();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user visible name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getName()
|
||||
{
|
||||
return __('Hardware Security Key (FIDO U2F)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user visible description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getDescription()
|
||||
{
|
||||
return __('Provides authentication using hardware security tokens supporting FIDO U2F, such as a YubiKey.');
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Second authentication factor handling
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Plugins\TwoFactor;
|
||||
|
||||
use PhpMyAdmin\Plugins\TwoFactorPlugin;
|
||||
|
||||
use function __;
|
||||
|
||||
/**
|
||||
* Simple two-factor authentication auth asking just for confirmation.
|
||||
*
|
||||
* This has no practical use, but can be used for testing.
|
||||
*/
|
||||
class Simple extends TwoFactorPlugin
|
||||
{
|
||||
/** @var string */
|
||||
public static $id = 'simple';
|
||||
|
||||
/**
|
||||
* Checks authentication, returns true on success
|
||||
*/
|
||||
public function check(): bool
|
||||
{
|
||||
return isset($_POST['2fa_confirm']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders user interface to enter two-factor authentication
|
||||
*
|
||||
* @return string HTML code
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return $this->template->render('login/twofactor/simple');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user visible name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getName()
|
||||
{
|
||||
return __('Simple two-factor authentication');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user visible description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getDescription()
|
||||
{
|
||||
return __('For testing purposes only!');
|
||||
}
|
||||
}
|
|
@ -1,246 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Plugins\TwoFactor;
|
||||
|
||||
use PhpMyAdmin\Plugins\TwoFactorPlugin;
|
||||
use PhpMyAdmin\ResponseRenderer;
|
||||
use PhpMyAdmin\TwoFactor;
|
||||
use PhpMyAdmin\WebAuthn\CustomServer;
|
||||
use PhpMyAdmin\WebAuthn\Server;
|
||||
use PhpMyAdmin\WebAuthn\WebauthnLibServer;
|
||||
use SodiumException;
|
||||
use Throwable;
|
||||
use Webauthn\Server as WebauthnServer;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
use function __;
|
||||
use function class_exists;
|
||||
use function is_array;
|
||||
use function is_string;
|
||||
use function json_decode;
|
||||
use function json_encode;
|
||||
use function random_bytes;
|
||||
use function sodium_base642bin;
|
||||
use function sodium_bin2base64;
|
||||
|
||||
use const SODIUM_BASE64_VARIANT_ORIGINAL;
|
||||
use const SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING;
|
||||
|
||||
/**
|
||||
* Two-factor authentication plugin for the WebAuthn/FIDO2 protocol.
|
||||
*/
|
||||
class WebAuthn extends TwoFactorPlugin
|
||||
{
|
||||
/** @var string */
|
||||
public static $id = 'WebAuthn';
|
||||
|
||||
/** @var Server */
|
||||
private $server;
|
||||
|
||||
public function __construct(TwoFactor $twofactor)
|
||||
{
|
||||
parent::__construct($twofactor);
|
||||
if (
|
||||
! isset($this->twofactor->config['settings']['userHandle'])
|
||||
|| ! is_string($this->twofactor->config['settings']['userHandle'])
|
||||
) {
|
||||
$this->twofactor->config['settings']['userHandle'] = '';
|
||||
}
|
||||
|
||||
if (
|
||||
! isset($this->twofactor->config['settings']['credentials'])
|
||||
|| ! is_array($this->twofactor->config['settings']['credentials'])
|
||||
) {
|
||||
$this->twofactor->config['settings']['credentials'] = [];
|
||||
}
|
||||
|
||||
$this->server = $this->createServer();
|
||||
}
|
||||
|
||||
private function createServer(): Server
|
||||
{
|
||||
return class_exists(WebauthnServer::class) ? new WebauthnLibServer($this->twofactor) : new CustomServer();
|
||||
}
|
||||
|
||||
public function setServer(Server $server): void
|
||||
{
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
public function render(): string
|
||||
{
|
||||
$request = $GLOBALS['request'];
|
||||
$userHandle = sodium_base642bin($this->getUserHandleFromSettings(), SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);
|
||||
$requestOptions = $this->server->getCredentialRequestOptions(
|
||||
$this->twofactor->user,
|
||||
$userHandle,
|
||||
$request->getUri()->getHost(),
|
||||
$this->getAllowedCredentials()
|
||||
);
|
||||
$requestOptionsEncoded = json_encode($requestOptions);
|
||||
$_SESSION['WebAuthnCredentialRequestOptions'] = $requestOptionsEncoded;
|
||||
$this->loadScripts();
|
||||
|
||||
return $this->template->render(
|
||||
'login/twofactor/webauthn_request',
|
||||
['request_options' => $requestOptionsEncoded]
|
||||
);
|
||||
}
|
||||
|
||||
public function check(): bool
|
||||
{
|
||||
$this->provided = false;
|
||||
$request = $GLOBALS['request'];
|
||||
$authenticatorResponse = $request->getParsedBodyParam('webauthn_request_response', '');
|
||||
if ($authenticatorResponse === '' || ! isset($_SESSION['WebAuthnCredentialRequestOptions'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->provided = true;
|
||||
|
||||
/** @var mixed $credentialRequestOptions */
|
||||
$credentialRequestOptions = $_SESSION['WebAuthnCredentialRequestOptions'];
|
||||
unset($_SESSION['WebAuthnCredentialRequestOptions']);
|
||||
|
||||
try {
|
||||
Assert::stringNotEmpty($authenticatorResponse);
|
||||
Assert::stringNotEmpty($credentialRequestOptions);
|
||||
$requestOptions = json_decode($credentialRequestOptions, true);
|
||||
Assert::isArray($requestOptions);
|
||||
Assert::keyExists($requestOptions, 'challenge');
|
||||
Assert::stringNotEmpty($requestOptions['challenge']);
|
||||
$this->server->parseAndValidateAssertionResponse(
|
||||
$authenticatorResponse,
|
||||
$this->getAllowedCredentials(),
|
||||
$requestOptions['challenge'],
|
||||
$request
|
||||
);
|
||||
} catch (Throwable $exception) {
|
||||
$this->message = $exception->getMessage();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setup(): string
|
||||
{
|
||||
$request = $GLOBALS['request'];
|
||||
$userId = sodium_bin2base64(random_bytes(32), SODIUM_BASE64_VARIANT_ORIGINAL);
|
||||
$host = $request->getUri()->getHost();
|
||||
$creationOptions = $this->server->getCredentialCreationOptions($this->twofactor->user, $userId, $host);
|
||||
$creationOptionsEncoded = json_encode($creationOptions);
|
||||
$_SESSION['WebAuthnCredentialCreationOptions'] = $creationOptionsEncoded;
|
||||
$this->loadScripts();
|
||||
|
||||
return $this->template->render(
|
||||
'login/twofactor/webauthn_creation',
|
||||
['creation_options' => $creationOptionsEncoded]
|
||||
);
|
||||
}
|
||||
|
||||
public function configure(): bool
|
||||
{
|
||||
$this->provided = false;
|
||||
$request = $GLOBALS['request'];
|
||||
$authenticatorResponse = $request->getParsedBodyParam('webauthn_creation_response', '');
|
||||
if ($authenticatorResponse === '' || ! isset($_SESSION['WebAuthnCredentialCreationOptions'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->provided = true;
|
||||
|
||||
/** @var mixed $credentialCreationOptions */
|
||||
$credentialCreationOptions = $_SESSION['WebAuthnCredentialCreationOptions'];
|
||||
unset($_SESSION['WebAuthnCredentialCreationOptions']);
|
||||
|
||||
try {
|
||||
Assert::stringNotEmpty($authenticatorResponse);
|
||||
Assert::stringNotEmpty($credentialCreationOptions);
|
||||
$credential = $this->server->parseAndValidateAttestationResponse(
|
||||
$authenticatorResponse,
|
||||
$credentialCreationOptions,
|
||||
$request
|
||||
);
|
||||
$this->saveCredential($credential);
|
||||
} catch (Throwable $exception) {
|
||||
$this->message = $exception->getMessage();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getName(): string
|
||||
{
|
||||
return __('Hardware Security Key (WebAuthn/FIDO2)');
|
||||
}
|
||||
|
||||
public static function getDescription(): string
|
||||
{
|
||||
return __(
|
||||
'Provides authentication using hardware security tokens supporting the WebAuthn/FIDO2 protocol,'
|
||||
. ' such as a YubiKey.'
|
||||
);
|
||||
}
|
||||
|
||||
private function loadScripts(): void
|
||||
{
|
||||
$response = ResponseRenderer::getInstance();
|
||||
$scripts = $response->getHeader()->getScripts();
|
||||
$scripts->addFile('webauthn.js');
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return list<array{id: non-empty-string, type: non-empty-string}>
|
||||
*/
|
||||
private function getAllowedCredentials(): array
|
||||
{
|
||||
$allowedCredentials = [];
|
||||
/** @psalm-var array<array<string, mixed>> $credentials */
|
||||
$credentials = $this->twofactor->config['settings']['credentials'];
|
||||
foreach ($credentials as $credential) {
|
||||
if (
|
||||
! is_string($credential['publicKeyCredentialId']) || $credential['publicKeyCredentialId'] === ''
|
||||
|| ! is_string($credential['type']) || $credential['type'] === ''
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$allowedCredentials[] = ['type' => $credential['type'], 'id' => $credential['publicKeyCredentialId']];
|
||||
}
|
||||
|
||||
return $allowedCredentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-param mixed[] $credential
|
||||
*
|
||||
* @throws SodiumException
|
||||
*/
|
||||
private function saveCredential(array $credential): void
|
||||
{
|
||||
Assert::keyExists($credential, 'publicKeyCredentialId');
|
||||
Assert::stringNotEmpty($credential['publicKeyCredentialId']);
|
||||
Assert::keyExists($credential, 'userHandle');
|
||||
Assert::string($credential['userHandle']);
|
||||
Assert::isArray($this->twofactor->config['settings']['credentials']);
|
||||
$id = sodium_bin2base64(
|
||||
sodium_base642bin($credential['publicKeyCredentialId'], SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING),
|
||||
SODIUM_BASE64_VARIANT_ORIGINAL
|
||||
);
|
||||
$this->twofactor->config['settings']['credentials'][$id] = $credential;
|
||||
$this->twofactor->config['settings']['userHandle'] = $credential['userHandle'];
|
||||
}
|
||||
|
||||
private function getUserHandleFromSettings(): string
|
||||
{
|
||||
Assert::string($this->twofactor->config['settings']['userHandle']);
|
||||
|
||||
return $this->twofactor->config['settings']['userHandle'];
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue