Skip to content

Commit

Permalink
[2.x] Fixes not decoding using BASE64 URL (#76)
Browse files Browse the repository at this point in the history
* [1.x] Fixes not decoding using BASE64 URL.
  • Loading branch information
DarkGhostHunter authored Mar 18, 2024
1 parent 4bdf3f2 commit 537add2
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 19 deletions.
7 changes: 4 additions & 3 deletions src/Assertion/Validator/Pipes/CheckPublicKeySignature.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Support\Str;
use Illuminate\Support\Stringable;
use Laragear\WebAuthn\Assertion\Validator\AssertionValidation;
use Laragear\WebAuthn\ByteBuffer;
use Laragear\WebAuthn\Exceptions\AssertionException;
use Laragear\WebAuthn\Models\WebAuthnCredential;

Expand Down Expand Up @@ -50,7 +51,7 @@ public function handle(AssertionValidation $validation, Closure $next): mixed
*/
protected function retrieveSignature(Request $request): string
{
$signature = base64_decode($request->json('response.signature', ''));
$signature = ByteBuffer::decodeBase64Url($request->json('response.signature', ''));

return $signature
?: throw AssertionException::make('Signature is empty.');
Expand All @@ -61,8 +62,8 @@ protected function retrieveSignature(Request $request): string
*/
protected function retrieveBinaryVerifiable(Request $request): string
{
$verifiable = base64_decode($request->json('response.authenticatorData')).
hash('sha256', base64_decode($request->json('response.clientDataJSON')), true);
$verifiable = ByteBuffer::decodeBase64Url($request->json('response.authenticatorData')).
hash('sha256', ByteBuffer::decodeBase64Url($request->json('response.clientDataJSON')), true);

return $verifiable
?: throw AssertionException::make('Authenticator Data or Client Data JSON are empty or malformed.');
Expand Down
5 changes: 2 additions & 3 deletions src/Assertion/Validator/Pipes/CompileAuthenticatorData.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
use Closure;
use Laragear\WebAuthn\Assertion\Validator\AssertionValidation;
use Laragear\WebAuthn\Attestation\AuthenticatorData;
use Laragear\WebAuthn\ByteBuffer;
use Laragear\WebAuthn\Exceptions\AssertionException;
use Laragear\WebAuthn\Exceptions\DataException;

use function base64_decode;

/**
* @internal
*/
Expand All @@ -22,7 +21,7 @@ class CompileAuthenticatorData
*/
public function handle(AssertionValidation $validation, Closure $next): mixed
{
$data = base64_decode($validation->request->json('response.authenticatorData', ''));
$data = ByteBuffer::decodeBase64Url($validation->request->json('response.authenticatorData', ''));

if (! $data) {
throw AssertionException::make('Authenticator Data does not exist or is empty.');
Expand Down
3 changes: 1 addition & 2 deletions src/Attestation/Validator/Pipes/CompileAttestationObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
use Laragear\WebAuthn\Exceptions\AttestationException;
use Laragear\WebAuthn\Exceptions\DataException;

use function base64_decode;
use function is_array;
use function is_string;

Expand Down Expand Up @@ -70,7 +69,7 @@ public function handle(AttestationValidation $validation, Closure $next): mixed
protected function decodeCborBase64(Request $request): array
{
try {
$data = CborDecoder::decode(base64_decode($request->json('response.attestationObject', '')));
$data = CborDecoder::decode(ByteBuffer::decodeBase64Url($request->json('response.attestationObject', '')));
} catch (DataException $e) {
throw AttestationException::make($e->getMessage());
}
Expand Down
4 changes: 2 additions & 2 deletions src/ByteBuffer.php
Original file line number Diff line number Diff line change
Expand Up @@ -390,15 +390,15 @@ public static function makeRandom(int $length): static
/**
* Decodes a BASE64 URL string.
*/
protected static function decodeBase64Url(string $data): string|false
public static function decodeBase64Url(string $data): string|false
{
return base64_decode(strtr($data, '-_', '+/').str_repeat('=', 3 - (3 + strlen($data)) % 4));
}

/**
* Encodes a BASE64 URL string.
*/
protected static function encodeBase64Url(string $data): string|false
public static function encodeBase64Url(string $data): string|false
{
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
Expand Down
6 changes: 4 additions & 2 deletions src/SharedPipes/CompileClientDataJson.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use Laragear\WebAuthn\ByteBuffer;
use Laragear\WebAuthn\ClientDataJson;

use function base64_decode;
use function json_decode;

use const JSON_THROW_ON_ERROR;
Expand All @@ -31,7 +30,8 @@ public function handle(AssertionValidation|AttestationValidation $validation, Cl
{
try {
$object = json_decode(
base64_decode($validation->request->json('response.clientDataJSON', '')), false, 32, JSON_THROW_ON_ERROR
ByteBuffer::decodeBase64Url($validation->request->json('response.clientDataJSON', '')),
false, 32, JSON_THROW_ON_ERROR
);
} catch (JsonException) {
static::throw($validation, 'Client Data JSON is invalid or malformed.');
Expand All @@ -41,6 +41,8 @@ public function handle(AssertionValidation|AttestationValidation $validation, Cl
static::throw($validation, 'Client Data JSON is empty.');
}

$object = (object) $object;

foreach (['type', 'origin', 'challenge'] as $key) {
if (! isset($object->{$key})) {
static::throw($validation, "Client Data JSON does not contain the [$key] key.");
Expand Down
6 changes: 4 additions & 2 deletions tests/Assertion/ValidationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ public function test_compiling_client_data_json_fails_if_empty(): void
{
$invalid = FakeAuthenticator::assertionResponse();

$invalid['response']['clientDataJSON'] = base64_encode(json_encode([]));
$invalid['response']['clientDataJSON'] = ByteBuffer::encodeBase64Url(json_encode([]));

$this->request->setJson(new ParameterBag($invalid));

Expand All @@ -334,7 +334,9 @@ public function test_compiling_client_data_json_fails_if_type_missing(): void
{
$invalid = FakeAuthenticator::assertionResponse();

$invalid['response']['clientDataJSON'] = base64_encode(json_encode(['origin' => '', 'challenge' => '']));
$invalid['response']['clientDataJSON'] = ByteBuffer::encodeBase64Url(json_encode([
'origin' => '', 'challenge' => '',
]));

$this->request->setJson(new ParameterBag($invalid));

Expand Down
12 changes: 7 additions & 5 deletions tests/Attestation/ValidationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,14 @@ public function test_compiling_client_data_json_fails_if_invalid(): void

public function test_compiling_client_data_json_fails_if_empty(): void
{
$this->expectException(AttestationException::class);
$this->expectExceptionMessage('Attestation Error: Client Data JSON is empty.');

$invalid = FakeAuthenticator::attestationResponse();

$invalid['response']['clientDataJSON'] = base64_encode(json_encode([]));
$invalid['response']['clientDataJSON'] = ByteBuffer::encodeBase64Url(json_encode([]));

$this->request->setJson(new ParameterBag($invalid));
$this->expectException(AttestationException::class);

$this->expectExceptionMessage('Attestation Error: Client Data JSON is empty.');

$this->validate();
}
Expand All @@ -199,7 +199,9 @@ public function test_compiling_client_data_json_fails_if_type_missing(): void

$invalid = FakeAuthenticator::attestationResponse();

$invalid['response']['clientDataJSON'] = base64_encode(json_encode(['origin' => '', 'challenge' => '']));
$invalid['response']['clientDataJSON'] = ByteBuffer::encodeBase64Url(json_encode([
'origin' => '', 'challenge' => '',
]));

$this->request->setJson(new ParameterBag($invalid));

Expand Down

0 comments on commit 537add2

Please sign in to comment.