Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new denormalizers and deprecate old JSON methods #618

Merged
merged 2 commits into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
87 changes: 80 additions & 7 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2421,6 +2421,41 @@ parameters:
count: 1
path: src/webauthn/src/Denormalizer/AttestationStatementDenormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\AttestedCredentialDataNormalizer\\:\\:normalize\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/AttestedCredentialDataNormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\AttestedCredentialDataNormalizer\\:\\:normalize\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/AttestedCredentialDataNormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\AttestedCredentialDataNormalizer\\:\\:supportsNormalization\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/AttestedCredentialDataNormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\AuthenticationExtensionNormalizer\\:\\:normalize\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/AuthenticationExtensionNormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\AuthenticationExtensionNormalizer\\:\\:normalize\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/AuthenticationExtensionNormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\AuthenticationExtensionNormalizer\\:\\:normalize\\(\\) should return array but returns mixed\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/AuthenticationExtensionNormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\AuthenticationExtensionNormalizer\\:\\:supportsNormalization\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/AuthenticationExtensionNormalizer.php

-
message: """
#^Fetching class constant class of deprecated class Webauthn\\\\AuthenticationExtensions\\\\AuthenticationExtensionsClientInputs\\:
Expand Down Expand Up @@ -2474,7 +2509,7 @@ parameters:

-
message: "#^Cannot access offset 'clientDataJSON' on mixed\\.$#"
count: 3
count: 2
path: src/webauthn/src/Denormalizer/AuthenticatorAssertionResponseDenormalizer.php

-
Expand All @@ -2484,7 +2519,7 @@ parameters:

-
message: "#^Cannot access offset 'userHandle' on mixed\\.$#"
count: 3
count: 1
path: src/webauthn/src/Denormalizer/AuthenticatorAssertionResponseDenormalizer.php

-
Expand Down Expand Up @@ -2522,11 +2557,6 @@ parameters:
count: 1
path: src/webauthn/src/Denormalizer/AuthenticatorAssertionResponseDenormalizer.php

-
message: "#^Parameter \\#4 \\$userHandle of static method Webauthn\\\\AuthenticatorAssertionResponse\\:\\:create\\(\\) expects string\\|null, mixed given\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/AuthenticatorAssertionResponseDenormalizer.php

-
message: "#^Parameter \\#5 \\$attestationObject of static method Webauthn\\\\AuthenticatorAssertionResponse\\:\\:create\\(\\) expects Webauthn\\\\AttestationStatement\\\\AttestationObject\\|null, mixed given\\.$#"
count: 1
Expand Down Expand Up @@ -2687,6 +2717,21 @@ parameters:
count: 1
path: src/webauthn/src/Denormalizer/PublicKeyCredentialDenormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\PublicKeyCredentialDescriptorNormalizer\\:\\:normalize\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/PublicKeyCredentialDescriptorNormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\PublicKeyCredentialDescriptorNormalizer\\:\\:normalize\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/PublicKeyCredentialDescriptorNormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\PublicKeyCredentialDescriptorNormalizer\\:\\:supportsNormalization\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/PublicKeyCredentialDescriptorNormalizer.php

-
message: "#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\\.$#"
count: 1
Expand Down Expand Up @@ -2962,11 +3007,26 @@ parameters:
count: 1
path: src/webauthn/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\PublicKeyCredentialSourceDenormalizer\\:\\:normalize\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\PublicKeyCredentialSourceDenormalizer\\:\\:normalize\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\PublicKeyCredentialSourceDenormalizer\\:\\:supportsDenormalization\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php

-
message: "#^Method Webauthn\\\\Denormalizer\\\\PublicKeyCredentialSourceDenormalizer\\:\\:supportsNormalization\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/webauthn/src/Denormalizer/PublicKeyCredentialSourceDenormalizer.php

-
message: "#^Parameter \\#1 \\$data of static method Webauthn\\\\Util\\\\Base64\\:\\:decode\\(\\) expects string, mixed given\\.$#"
count: 1
Expand Down Expand Up @@ -3292,3 +3352,16 @@ parameters:
message: "#^Parameter \\#1 \\$ecdaaKeyId of class Webauthn\\\\TrustPath\\\\EcdaaKeyIdTrustPath constructor expects string, mixed given\\.$#"
count: 1
path: src/webauthn/src/TrustPath/EcdaaKeyIdTrustPath.php

-
message: """
#^Instantiation of deprecated class Webauthn\\\\TrustPath\\\\EcdaaKeyIdTrustPath\\:
since 4\\.2\\.0 and will be removed in 5\\.0\\.0\\. The ECDAA Trust Anchor does no longer exist in Webauthn specification\\.$#
"""
count: 1
path: src/webauthn/src/TrustPath/TrustPathLoader.php

-
message: "#^Parameter \\#1 \\$certificates of static method Webauthn\\\\TrustPath\\\\CertificateTrustPath\\:\\:create\\(\\) expects array\\<string\\>, array given\\.$#"
count: 1
path: src/webauthn/src/TrustPath/TrustPathLoader.php
57 changes: 45 additions & 12 deletions src/symfony/src/DataCollector/WebauthnCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
use Symfony\Component\Serializer\Encoder\JsonEncode;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Throwable;
Expand Down Expand Up @@ -52,6 +56,11 @@ class WebauthnCollector extends DataCollector implements EventSubscriberInterfac
*/
private array $authenticatorAssertionResponseValidationFailed = [];

public function __construct(
private readonly SerializerInterface $serializer
) {
}

public function collect(Request $request, Response $response, ?Throwable $exception = null): void
{
$this->data = [
Expand Down Expand Up @@ -110,9 +119,13 @@ public function addPublicKeyCredentialCreationOptions(PublicKeyCredentialCreatio
$cloner = new VarCloner();
$this->publicKeyCredentialCreationOptions[] = [
'options' => $cloner->cloneVar($event->publicKeyCredentialCreationOptions),
'json' => json_encode(
'json' => $this->serializer->serialize(
$event->publicKeyCredentialCreationOptions,
JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT
JsonEncoder::FORMAT,
[
AbstractObjectNormalizer::SKIP_NULL_VALUES => true,
JsonEncode::OPTIONS => JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT,
]
),
];
}
Expand All @@ -124,9 +137,13 @@ public function addAuthenticatorAttestationResponseValidationSucceeded(
$this->authenticatorAttestationResponseValidationSucceeded[] = [
'attestation_response' => $cloner->cloneVar($event->authenticatorAttestationResponse),
'options' => $cloner->cloneVar($event->publicKeyCredentialCreationOptions),
'options_json' => json_encode(
'options_json' => $this->serializer->serialize(
$event->publicKeyCredentialCreationOptions,
JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT
JsonEncoder::FORMAT,
[
AbstractObjectNormalizer::SKIP_NULL_VALUES => true,
JsonEncode::OPTIONS => JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT,
]
),
'credential_source' => $cloner->cloneVar($event->publicKeyCredentialSource),
];
Expand All @@ -139,9 +156,13 @@ public function addAuthenticatorAttestationResponseValidationFailed(
$this->authenticatorAttestationResponseValidationFailed[] = [
'attestation_response' => $cloner->cloneVar($event->authenticatorAttestationResponse),
'options' => $cloner->cloneVar($event->publicKeyCredentialCreationOptions),
'options_json' => json_encode(
'options_json' => $this->serializer->serialize(
$event->publicKeyCredentialCreationOptions,
JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT
JsonEncoder::FORMAT,
[
AbstractObjectNormalizer::SKIP_NULL_VALUES => true,
JsonEncode::OPTIONS => JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT,
]
),
'exception' => $cloner->cloneVar($event->throwable),
];
Expand All @@ -152,9 +173,13 @@ public function addPublicKeyCredentialRequestOptions(PublicKeyCredentialRequestO
$cloner = new VarCloner();
$this->publicKeyCredentialRequestOptions[] = [
'options' => $cloner->cloneVar($event->publicKeyCredentialRequestOptions),
'json' => json_encode(
'json' => $this->serializer->serialize(
$event->publicKeyCredentialRequestOptions,
JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT
JsonEncoder::FORMAT,
[
AbstractObjectNormalizer::SKIP_NULL_VALUES => true,
JsonEncode::OPTIONS => JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT,
]
),
];
}
Expand All @@ -168,9 +193,13 @@ public function addAuthenticatorAssertionResponseValidationSucceeded(
'credential_id' => $cloner->cloneVar($event->credentialId),
'assertion_response' => $cloner->cloneVar($event->authenticatorAssertionResponse),
'options' => $cloner->cloneVar($event->publicKeyCredentialRequestOptions),
'options_json' => json_encode(
'options_json' => $this->serializer->serialize(
$event->publicKeyCredentialRequestOptions,
JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT
JsonEncoder::FORMAT,
[
AbstractObjectNormalizer::SKIP_NULL_VALUES => true,
JsonEncode::OPTIONS => JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT,
]
),
'credential_source' => $cloner->cloneVar($event->publicKeyCredentialSource),
];
Expand All @@ -185,9 +214,13 @@ public function addAuthenticatorAssertionResponseValidationFailed(
'credential_id' => $cloner->cloneVar($event->getCredential()?->publicKeyCredentialId),
'assertion_response' => $cloner->cloneVar($event->authenticatorAssertionResponse),
'options' => $cloner->cloneVar($event->publicKeyCredentialRequestOptions),
'options_json' => json_encode(
'options_json' => $this->serializer->serialize(
$event->publicKeyCredentialRequestOptions,
JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT
JsonEncoder::FORMAT,
[
AbstractObjectNormalizer::SKIP_NULL_VALUES => true,
JsonEncode::OPTIONS => JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT,
]
),
'exception' => $cloner->cloneVar($event->throwable),
];
Expand Down
2 changes: 2 additions & 0 deletions src/symfony/src/Resources/config/dev_services.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Webauthn\Bundle\DataCollector;

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

return static function (ContainerConfigurator $container): void {
$container = $container->services()
Expand All @@ -13,6 +14,7 @@
->autoconfigure();

$container->set(WebauthnCollector::class)
->args([service('serializer')])
->tag('data_collector', [
'id' => 'webauthn_collector',
'template' => '@Webauthn/data_collector/template.html.twig',
Expand Down
6 changes: 4 additions & 2 deletions src/symfony/src/Resources/config/security.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@
$container->set(DefaultFailureHandler::class);
$container->set(SessionStorage::class)->args([service('request_stack')]);
$container->set(CacheStorage::class)->args([service(CacheItemPoolInterface::class)]);
$container->set(DefaultCreationOptionsHandler::class);
$container->set(DefaultRequestOptionsHandler::class);
$container->set(DefaultCreationOptionsHandler::class)
->args([service('serializer')]);
$container->set(DefaultRequestOptionsHandler::class)
->args([service('serializer')]);
$container
->set(WebauthnFactory::AUTHENTICATOR_DEFINITION_ID, WebauthnAuthenticator::class)
->abstract()
Expand Down
18 changes: 18 additions & 0 deletions src/symfony/src/Resources/config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@
use Webauthn\Counter\ThrowExceptionIfInvalid;
use Webauthn\Denormalizer\AttestationObjectDenormalizer;
use Webauthn\Denormalizer\AttestationStatementDenormalizer;
use Webauthn\Denormalizer\AttestedCredentialDataNormalizer;
use Webauthn\Denormalizer\AuthenticationExtensionNormalizer;
use Webauthn\Denormalizer\AuthenticationExtensionsDenormalizer;
use Webauthn\Denormalizer\AuthenticatorAssertionResponseDenormalizer;
use Webauthn\Denormalizer\AuthenticatorAttestationResponseDenormalizer;
use Webauthn\Denormalizer\AuthenticatorDataDenormalizer;
use Webauthn\Denormalizer\AuthenticatorResponseDenormalizer;
use Webauthn\Denormalizer\CollectedClientDataDenormalizer;
use Webauthn\Denormalizer\PublicKeyCredentialDenormalizer;
use Webauthn\Denormalizer\PublicKeyCredentialDescriptorNormalizer;
use Webauthn\Denormalizer\PublicKeyCredentialOptionsDenormalizer;
use Webauthn\Denormalizer\PublicKeyCredentialSourceDenormalizer;
use Webauthn\Denormalizer\PublicKeyCredentialUserEntityDenormalizer;
Expand Down Expand Up @@ -209,6 +212,21 @@
->tag('serializer.normalizer', [
'priority' => 1024,
]);
$container
->set(AuthenticationExtensionNormalizer::class)
->tag('serializer.normalizer', [
'priority' => 1024,
]);
$container
->set(PublicKeyCredentialDescriptorNormalizer::class)
->tag('serializer.normalizer', [
'priority' => 1024,
]);
$container
->set(AttestedCredentialDataNormalizer::class)
->tag('serializer.normalizer', [
'priority' => 1024,
]);
$container
->set(AuthenticationExtensionsDenormalizer::class)
->tag('serializer.normalizer', [
Expand Down
18 changes: 11 additions & 7 deletions src/symfony/src/Security/Handler/DefaultCreationOptionsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,27 @@
use RuntimeException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Webauthn\PublicKeyCredentialCreationOptions;
use Webauthn\PublicKeyCredentialUserEntity;
use function is_array;
use const JSON_THROW_ON_ERROR;

final class DefaultCreationOptionsHandler implements CreationOptionsHandler
{
public function __construct(
private readonly NormalizerInterface $normalizer
) {
}

public function onCreationOptions(
PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions,
PublicKeyCredentialUserEntity $userEntity
): Response {
$data = json_decode(
json_encode($publicKeyCredentialCreationOptions, JSON_THROW_ON_ERROR),
true,
512,
JSON_THROW_ON_ERROR
);
$data = $this->normalizer->normalize($publicKeyCredentialCreationOptions, JsonEncoder::FORMAT, [
AbstractObjectNormalizer::SKIP_NULL_VALUES => true,
]);
is_array($data) || throw new RuntimeException('Unable to encode the response to JSON.');
$data['status'] = 'ok';
$data['errorMessage'] = '';
Expand Down
18 changes: 11 additions & 7 deletions src/symfony/src/Security/Handler/DefaultRequestOptionsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,27 @@
use RuntimeException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Webauthn\PublicKeyCredentialRequestOptions;
use Webauthn\PublicKeyCredentialUserEntity;
use function is_array;
use const JSON_THROW_ON_ERROR;

final class DefaultRequestOptionsHandler implements RequestOptionsHandler
{
public function __construct(
private readonly NormalizerInterface $normalizer
) {
}

public function onRequestOptions(
PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions,
?PublicKeyCredentialUserEntity $userEntity
): Response {
$data = json_decode(
json_encode($publicKeyCredentialRequestOptions, JSON_THROW_ON_ERROR),
true,
512,
JSON_THROW_ON_ERROR
);
$data = $this->normalizer->normalize($publicKeyCredentialRequestOptions, JsonEncoder::FORMAT, [
AbstractObjectNormalizer::SKIP_NULL_VALUES => true,
]);
is_array($data) || throw new RuntimeException('Unable to encode the response to JSON.');
$data['status'] = 'ok';
$data['errorMessage'] = '';
Expand Down
Loading