MDL-84175 libraries: Upgrade WebAuthn to 2.2.0
Signed-off-by: Daniel Ziegenberg <[email protected]>
This commit is contained in:
@@ -737,7 +737,7 @@ All rights reserved.</copyright>
|
||||
<library>
|
||||
<location>webauthn</location>
|
||||
<name>WebAuthn</name>
|
||||
<version>2.1.1</version>
|
||||
<version>2.2.2</version>
|
||||
<license>MIT</license>
|
||||
<repository>https://github.com/lbuchs/WebAuthn</repository>
|
||||
</library>
|
||||
|
||||
+24
-23
@@ -19,7 +19,8 @@ See /_test for a simple usage of this library. Check [webauthn.lubu.ch](https://
|
||||
* packed ✅
|
||||
* tpm ✅
|
||||
|
||||
This library supports authenticators which are signed with a X.509 certificate or which are self attested. ECDAA is not supported.
|
||||
> [!NOTE]
|
||||
> This library supports authenticators which are signed with a X.509 certificate or which are self attested. ECDAA is not supported.
|
||||
|
||||
## Workflow
|
||||
|
||||
@@ -60,39 +61,44 @@ their organization.
|
||||
### no attestation
|
||||
just verify that the device is the same device used on registration.
|
||||
You can use 'none' attestation with this library if you only check 'none' as format.
|
||||
* this is propably what you want to use if you want simple 2FA login protection like github, facebook, google, etc.
|
||||
|
||||
> [!TIP]
|
||||
> this is propably what you want to use if you want secure login for a public website.
|
||||
|
||||
### indirect attestation
|
||||
the browser may replace the AAGUID and attestation statement with a more privacy-friendly and/or more easily
|
||||
verifiable version of the same data (for example, by employing an anonymization CA).
|
||||
You can not validate against any root ca, if the browser uses a anonymization certificate.
|
||||
this library sets attestation to indirect, if you select multiple formats but don't provide any root ca.
|
||||
* hybrid soultion, clients may be discouraged by browser warnings but then you know what device they're using (statistics rulez!)
|
||||
|
||||
> [!TIP]
|
||||
> hybrid soultion, clients may be discouraged by browser warnings but then you know what device they're using (statistics rulez!)
|
||||
|
||||
### direct attestation
|
||||
the browser proviedes data about the identificator device, the device can be identified uniquely. User could be tracked over multiple sites, because of that the browser may show a warning message about providing this data when register.
|
||||
this library sets attestation to direct, if you select multiple formats and provide root ca's.
|
||||
* this is probably what you want if you know what devices your clients are using and make sure that only this devices are used.
|
||||
|
||||
## Client-side discoverable Credentials
|
||||
> [!TIP]
|
||||
> this is probably what you want if you know what devices your clients are using and make sure that only this devices are used.
|
||||
|
||||
## Passkeys / Client-side discoverable Credentials
|
||||
A Client-side discoverable Credential Source is a public key credential source whose credential private key is stored in the authenticator,
|
||||
client or client device. Such client-side storage requires a resident credential capable authenticator.
|
||||
This is only supported by FIDO2 hardware, not by older U2F hardware.
|
||||
|
||||
>[!NOTE]
|
||||
>Passkeys is a technique that allows sharing credentials stored on the device with other devices. So from a technical standpoint of the server, there is no difference to client-side discoverable credentials. The difference is only that the phone or computer system is automatically syncing the credentials between the user’s devices via a cloud service. The cross-device sync of passkeys is managed transparently by the OS.
|
||||
|
||||
### How does it work?
|
||||
In a typical **server-side key** process, the user provides their username (and sometimes password)
|
||||
and the server responds with a list of all the public key credential identifiers that the user has registered.
|
||||
The authenticator then selects the first credential identifier it issued and responds with a signature
|
||||
that can be verified using the public key registered during the registration process.
|
||||
In a typical server-side key management process, a user initiates a request by entering their username and, in some cases, their password.
|
||||
The server validates the user's credentials and, upon successful authentication, retrieves a list of all public key identifiers associated with that user account.
|
||||
This list is then returned to the authenticator, which selects the first credential identifier it issued and responds with a signature that can be verified using the public key registered during the registration process.
|
||||
|
||||
In a client-side key process, the user does not need to provide a username or password.
|
||||
Instead, the authenticator searches its own memory to see if it has saved a key for the relying party.
|
||||
Instead, the authenticator searches its own memory to see if it has saved a key for the relying party (domain).
|
||||
If a key is found, the authentication process proceeds in the same way as it would if the server had sent a list
|
||||
of identifiers. There is no difference in the verification process.
|
||||
|
||||
Both Apple and Windows 10/11 (with Firefox and Chromium) support Resident Credential.
|
||||
However, older operating systems such as Windows 7 do not support it and instead fall back to using FIDO U2F.
|
||||
|
||||
### How can I use it with this library?
|
||||
#### on registration
|
||||
When calling `WebAuthn\WebAuthn->getCreateArgs`, set `$requireResidentKey` to true,
|
||||
@@ -100,21 +106,16 @@ to notify the authenticator that he should save the registration in its memory.
|
||||
|
||||
#### on login
|
||||
When calling `WebAuthn\WebAuthn->getGetArgs`, don't provide any `$credentialIds` (the authenticator will look up the ids in its own memory and returns the user ID as userHandle).
|
||||
Set the type of authenticator to `hybrid` (Passkey scanned via QR Code) and `internal` (Passkey stored on the device itself).
|
||||
|
||||
#### disadvantage
|
||||
The RP ID (= domain) is saved on the authenticator. So If an authenticator is lost, its theoretically possible to find the services, which the authenticator is used and login there.
|
||||
|
||||
## Passkeys
|
||||
Passkeys is a technique that allows sharing credentials stored on the device with other devices. So from a technical standpoint of the server,
|
||||
there is no difference to client-side discoverable credentials. The difference is only that the phone or computer system is automatically
|
||||
syncing the credentials between the user’s devices via a cloud service. The cross-device sync of passkeys is managed transparently by the OS.
|
||||
|
||||
### Browser support
|
||||
### device support
|
||||
Availability of built-in passkeys that automatically synchronize to all of a user’s devices: (see also [passkeys.dev/device-support](https://passkeys.dev/device-support/))
|
||||
* Apple: iOS 16 / iPadOS 16 / macOS Ventura
|
||||
* Google: support in Android starting October 2022
|
||||
* Microsoft Windows is set to deliver support in 2023.
|
||||
* Firefox see [Bugzilla](https://bugzilla.mozilla.org/show_bug.cgi?id=1792433)
|
||||
* Apple iOS 16+ / iPadOS 16+ / macOS Ventura+
|
||||
* Android 9+
|
||||
* Microsoft Windows 11 23H2+
|
||||
|
||||
## Requirements
|
||||
* PHP >= 8.0 with [OpenSSL](http://php.net/manual/en/book.openssl.php) and [Multibyte String](https://www.php.net/manual/en/book.mbstring.php)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
WebAuthn 2.0.1
|
||||
WebAuthn
|
||||
--------------
|
||||
|
||||
https://github.com/lbuchs/WebAuthn
|
||||
|
||||
Instructions to import WebAuthn into Moodle:
|
||||
|
||||
@@ -189,6 +189,24 @@ class AuthenticatorData {
|
||||
return $this->_flags->userVerified;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if the backup is eligible
|
||||
* @return boolean
|
||||
*/
|
||||
public function getIsBackupEligible()
|
||||
{
|
||||
return $this->_flags->isBackupEligible;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if the current credential is backed up
|
||||
* @return boolean
|
||||
*/
|
||||
public function getIsBackup()
|
||||
{
|
||||
return $this->_flags->isBackup;
|
||||
}
|
||||
|
||||
// -----------------------------------------------
|
||||
// PRIVATE
|
||||
// -----------------------------------------------
|
||||
@@ -259,6 +277,8 @@ class AuthenticatorData {
|
||||
// named flags
|
||||
$flags->userPresent = $flags->bit_0;
|
||||
$flags->userVerified = $flags->bit_2;
|
||||
$flags->isBackupEligible = $flags->bit_3;
|
||||
$flags->isBackup = $flags->bit_4;
|
||||
$flags->attestedDataIncluded = $flags->bit_6;
|
||||
$flags->extensionDataIncluded = $flags->bit_7;
|
||||
return $flags;
|
||||
|
||||
@@ -89,7 +89,7 @@ abstract class FormatBase {
|
||||
|
||||
/**
|
||||
* creates a PEM encoded chain file
|
||||
* @return type
|
||||
* @return string|null
|
||||
*/
|
||||
protected function _createX5cChainFile() {
|
||||
$content = '';
|
||||
|
||||
@@ -30,6 +30,7 @@ class WebAuthn {
|
||||
private $_signatureCounter;
|
||||
private $_caFiles;
|
||||
private $_formats;
|
||||
private $_androidKeyHashes;
|
||||
|
||||
/**
|
||||
* Initialize a new WebAuthn server
|
||||
@@ -90,6 +91,23 @@ class WebAuthn {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add key hashes for android verification
|
||||
* @param array<string> $hashes
|
||||
* @return void
|
||||
*/
|
||||
public function addAndroidKeyHashes($hashes) {
|
||||
if (!\is_array($this->_androidKeyHashes)) {
|
||||
$this->_androidKeyHashes = [];
|
||||
}
|
||||
|
||||
foreach ($hashes as $hash) {
|
||||
if (is_string($hash)) {
|
||||
$this->_androidKeyHashes[] = $hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the generated challenge to save for later validation
|
||||
* @return ByteBuffer
|
||||
@@ -397,6 +415,8 @@ class WebAuthn {
|
||||
$data->rootValid = $rootValid;
|
||||
$data->userPresent = $userPresent;
|
||||
$data->userVerified = $userVerified;
|
||||
$data->isBackupEligible = $attestationObject->getAuthenticatorData()->getIsBackupEligible();
|
||||
$data->isBackedUp = $attestationObject->getAuthenticatorData()->getIsBackup();
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -601,6 +621,10 @@ class WebAuthn {
|
||||
* @throws WebAuthnException
|
||||
*/
|
||||
private function _checkOrigin($origin) {
|
||||
if (str_starts_with($origin, 'android:apk-key-hash:')) {
|
||||
return $this->_checkAndroidKeyHashes($origin);
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/webauthn/#rp-id
|
||||
|
||||
// The origin's scheme must be https
|
||||
@@ -617,6 +641,19 @@ class WebAuthn {
|
||||
return \preg_match('/' . \preg_quote($this->_rpId) . '$/i', $host) === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if the origin value contains a known android key hash
|
||||
* @param string $origin
|
||||
* @return boolean
|
||||
*/
|
||||
private function _checkAndroidKeyHashes($origin) {
|
||||
$parts = explode('android:apk-key-hash:', $origin);
|
||||
if (count($parts) !== 2) {
|
||||
return false;
|
||||
}
|
||||
return in_array($parts[1], $this->_androidKeyHashes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* generates a new challange
|
||||
* @param int $length
|
||||
|
||||
Reference in New Issue
Block a user