diff --git a/phpstan.neon b/phpstan.neon index 24efc2fb..426041cd 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -65,8 +65,10 @@ parameters: message: '#Strict comparison using === between mixed and null will always evaluate to false\.#' path: src/metadata-service/src/Statement/StatusReport.php count: 1 + - '#Fetching class constant class of deprecated class Webauthn\\PublicKeyCredentialSourceRepository\.#' - '#Fetching class constant class of deprecated class Webauthn\\Bundle\\Repository\\PublicKeyCredentialUserEntityRepository.*#' - '#.*Binding.*#' + - '#Parameter .* of method .* has typehint with deprecated interface Webauthn\\PublicKeyCredentialSourceRepository\.#' - '#Parameter \#\d+ \$.* of .* expects .*, .* given\.#' - '#Property .* does not accept .*\|false\.#' - '#Cannot access offset \d+ on array\|false\.#' diff --git a/src/symfony/src/Controller/AssertionControllerFactory.php b/src/symfony/src/Controller/AssertionControllerFactory.php index 18e3c2c6..0c1f7a7d 100644 --- a/src/symfony/src/Controller/AssertionControllerFactory.php +++ b/src/symfony/src/Controller/AssertionControllerFactory.php @@ -12,6 +12,7 @@ use Webauthn\AuthenticatorAssertionResponseValidator; use Webauthn\Bundle\CredentialOptionsBuilder\ProfileBasedRequestOptionsBuilder; use Webauthn\Bundle\CredentialOptionsBuilder\PublicKeyCredentialRequestOptionsBuilder; +use Webauthn\Bundle\Repository\PublicKeyCredentialSourceRepositoryInterface; use Webauthn\Bundle\Repository\PublicKeyCredentialUserEntityRepositoryInterface; use Webauthn\Bundle\Security\Handler\FailureHandler; use Webauthn\Bundle\Security\Handler\RequestOptionsHandler; @@ -33,7 +34,7 @@ public function __construct( private readonly PublicKeyCredentialLoader $publicKeyCredentialLoader, private readonly AuthenticatorAssertionResponseValidator $attestationResponseValidator, private readonly PublicKeyCredentialUserEntityRepositoryInterface $publicKeyCredentialUserEntityRepository, - private readonly PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository + private readonly PublicKeyCredentialSourceRepository|PublicKeyCredentialSourceRepositoryInterface $publicKeyCredentialSourceRepository ) { $this->logger = new NullLogger(); } @@ -113,7 +114,8 @@ public function createResponseController( $optionStorage, $successHandler, $failureHandler, - $securedRelyingPartyIds + $securedRelyingPartyIds, + $this->publicKeyCredentialSourceRepository ); } } diff --git a/src/symfony/src/Controller/AssertionResponseController.php b/src/symfony/src/Controller/AssertionResponseController.php index e12392ee..8f31b7e9 100644 --- a/src/symfony/src/Controller/AssertionResponseController.php +++ b/src/symfony/src/Controller/AssertionResponseController.php @@ -13,9 +13,11 @@ use Throwable; use Webauthn\AuthenticatorAssertionResponse; use Webauthn\AuthenticatorAssertionResponseValidator; +use Webauthn\Bundle\Repository\PublicKeyCredentialSourceRepositoryInterface; use Webauthn\Bundle\Security\Handler\FailureHandler; use Webauthn\Bundle\Security\Handler\SuccessHandler; use Webauthn\Bundle\Security\Storage\OptionsStorage; +use Webauthn\Exception\AuthenticatorResponseVerificationException; use Webauthn\PublicKeyCredentialLoader; use Webauthn\PublicKeyCredentialRequestOptions; @@ -32,6 +34,7 @@ public function __construct( private readonly SuccessHandler $successHandler, private readonly FailureHandler|AuthenticationFailureHandlerInterface $failureHandler, private readonly array $securedRelyingPartyIds, + private readonly ?PublicKeyCredentialSourceRepositoryInterface $publicKeyCredentialSourceRepository = null ) { } @@ -55,8 +58,15 @@ public function __invoke(Request $request): Response 'Invalid response' ); $userEntity = $data->getPublicKeyCredentialUserEntity(); + $publicKeyCredentialSource = $this->publicKeyCredentialSourceRepository === null ? $publicKeyCredential->getRawId() : $this->publicKeyCredentialSourceRepository->findOneByCredentialId( + $publicKeyCredential->getRawId() + ); + $publicKeyCredentialSource !== null || throw AuthenticatorResponseVerificationException::create( + 'The credential ID is invalid.' + ); + $this->assertionResponseValidator->check( - $publicKeyCredential->getRawId(), + $publicKeyCredentialSource, $response, $publicKeyCredentialRequestOptions, $request->getHost(), diff --git a/src/symfony/src/Controller/AttestationControllerFactory.php b/src/symfony/src/Controller/AttestationControllerFactory.php index 0d0e4475..26f71ffd 100644 --- a/src/symfony/src/Controller/AttestationControllerFactory.php +++ b/src/symfony/src/Controller/AttestationControllerFactory.php @@ -10,6 +10,7 @@ use Webauthn\AuthenticatorAttestationResponseValidator; use Webauthn\Bundle\CredentialOptionsBuilder\ProfileBasedCreationOptionsBuilder; use Webauthn\Bundle\CredentialOptionsBuilder\PublicKeyCredentialCreationOptionsBuilder; +use Webauthn\Bundle\Repository\PublicKeyCredentialSourceRepositoryInterface; use Webauthn\Bundle\Security\Guesser\UserEntityGuesser; use Webauthn\Bundle\Security\Handler\CreationOptionsHandler; use Webauthn\Bundle\Security\Handler\FailureHandler; @@ -27,7 +28,7 @@ public function __construct( private readonly PublicKeyCredentialCreationOptionsFactory $publicKeyCredentialCreationOptionsFactory, private readonly PublicKeyCredentialLoader $publicKeyCredentialLoader, private readonly AuthenticatorAttestationResponseValidator $attestationResponseValidator, - private readonly PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository + private readonly PublicKeyCredentialSourceRepository|PublicKeyCredentialSourceRepositoryInterface $publicKeyCredentialSourceRepository ) { } diff --git a/src/symfony/src/Controller/AttestationResponseController.php b/src/symfony/src/Controller/AttestationResponseController.php index fa976063..a43c61c9 100644 --- a/src/symfony/src/Controller/AttestationResponseController.php +++ b/src/symfony/src/Controller/AttestationResponseController.php @@ -12,6 +12,10 @@ use Throwable; use Webauthn\AuthenticatorAttestationResponse; use Webauthn\AuthenticatorAttestationResponseValidator; +use Webauthn\Bundle\Exception\HttpNotImplementedException; +use Webauthn\Bundle\Exception\MissingFeatureException; +use Webauthn\Bundle\Repository\CanSaveCredentialSource; +use Webauthn\Bundle\Repository\PublicKeyCredentialSourceRepositoryInterface; use Webauthn\Bundle\Security\Handler\FailureHandler; use Webauthn\Bundle\Security\Handler\SuccessHandler; use Webauthn\Bundle\Security\Storage\OptionsStorage; @@ -28,17 +32,31 @@ final class AttestationResponseController public function __construct( private readonly PublicKeyCredentialLoader $publicKeyCredentialLoader, private readonly AuthenticatorAttestationResponseValidator $attestationResponseValidator, - private readonly PublicKeyCredentialSourceRepository $credentialSourceRepository, + private readonly PublicKeyCredentialSourceRepository|PublicKeyCredentialSourceRepositoryInterface $credentialSourceRepository, private readonly OptionsStorage $optionStorage, private readonly SuccessHandler $successHandler, private readonly FailureHandler|AuthenticationFailureHandlerInterface $failureHandler, private readonly array $securedRelyingPartyIds, ) { + if (! $this->credentialSourceRepository instanceof PublicKeyCredentialSourceRepositoryInterface) { + trigger_deprecation( + 'web-auth/webauthn-symfony-bundle', + '4.6.0', + sprintf( + 'Since 4.6.0, the parameter "$credentialSourceRepository" expects an instance of "%s". Please implement that interface instead of "%s".', + PublicKeyCredentialSourceRepositoryInterface::class, + PublicKeyCredentialSourceRepository::class + ) + ); + } } public function __invoke(Request $request): Response { try { + if (! $this->credentialSourceRepository instanceof CanSaveCredentialSource) { + throw MissingFeatureException::create('Unable to register the credential.'); + } $format = method_exists( $request, 'getContentTypeFormat' @@ -73,13 +91,14 @@ public function __invoke(Request $request): Response $this->credentialSourceRepository->saveCredentialSource($credentialSource); return $this->successHandler->onSuccess($request); } catch (Throwable $throwable) { + $exception = new AuthenticationException($throwable->getMessage(), 401, $throwable); + if ($throwable instanceof MissingFeatureException) { + $exception = new HttpNotImplementedException($throwable->getMessage(), $throwable); + } if ($this->failureHandler instanceof AuthenticationFailureHandlerInterface) { - return $this->failureHandler->onAuthenticationFailure( - $request, - new AuthenticationException($throwable->getMessage(), $throwable->getCode(), $throwable) - ); + return $this->failureHandler->onAuthenticationFailure($request, $exception); } - return $this->failureHandler->onFailure($request, $throwable); + return $this->failureHandler->onFailure($request, $exception); } } } diff --git a/src/symfony/src/CredentialOptionsBuilder/ProfileBasedCreationOptionsBuilder.php b/src/symfony/src/CredentialOptionsBuilder/ProfileBasedCreationOptionsBuilder.php index 11f1d98b..9a6111a5 100644 --- a/src/symfony/src/CredentialOptionsBuilder/ProfileBasedCreationOptionsBuilder.php +++ b/src/symfony/src/CredentialOptionsBuilder/ProfileBasedCreationOptionsBuilder.php @@ -15,6 +15,7 @@ use Webauthn\AuthenticationExtensions\AuthenticationExtensionsClientInputs; use Webauthn\AuthenticatorSelectionCriteria; use Webauthn\Bundle\Dto\PublicKeyCredentialCreationOptionsRequest; +use Webauthn\Bundle\Repository\PublicKeyCredentialSourceRepositoryInterface; use Webauthn\Bundle\Service\PublicKeyCredentialCreationOptionsFactory; use Webauthn\PublicKeyCredentialCreationOptions; use Webauthn\PublicKeyCredentialDescriptor; @@ -27,10 +28,21 @@ final class ProfileBasedCreationOptionsBuilder implements PublicKeyCredentialCre public function __construct( private readonly SerializerInterface $serializer, private readonly ValidatorInterface $validator, - private readonly PublicKeyCredentialSourceRepository $credentialSourceRepository, + private readonly PublicKeyCredentialSourceRepository|PublicKeyCredentialSourceRepositoryInterface $credentialSourceRepository, private readonly PublicKeyCredentialCreationOptionsFactory $publicKeyCredentialCreationOptionsFactory, private readonly string $profile, ) { + if (! $this->credentialSourceRepository instanceof PublicKeyCredentialSourceRepositoryInterface) { + trigger_deprecation( + 'web-auth/webauthn-symfony-bundle', + '4.6.0', + sprintf( + 'Since 4.6.0, the parameter "$credentialSourceRepository" expects an instance of "%s". Please implement that interface instead of "%s".', + PublicKeyCredentialSourceRepositoryInterface::class, + PublicKeyCredentialSourceRepository::class + ) + ); + } } public function getFromRequest( diff --git a/src/symfony/src/CredentialOptionsBuilder/ProfileBasedRequestOptionsBuilder.php b/src/symfony/src/CredentialOptionsBuilder/ProfileBasedRequestOptionsBuilder.php index 1fe2f9ef..cbbf4a44 100644 --- a/src/symfony/src/CredentialOptionsBuilder/ProfileBasedRequestOptionsBuilder.php +++ b/src/symfony/src/CredentialOptionsBuilder/ProfileBasedRequestOptionsBuilder.php @@ -12,6 +12,7 @@ use Symfony\Component\Validator\Validator\ValidatorInterface; use Webauthn\AuthenticationExtensions\AuthenticationExtensionsClientInputs; use Webauthn\Bundle\Dto\ServerPublicKeyCredentialRequestOptionsRequest; +use Webauthn\Bundle\Repository\PublicKeyCredentialSourceRepositoryInterface; use Webauthn\Bundle\Repository\PublicKeyCredentialUserEntityRepositoryInterface; use Webauthn\Bundle\Service\PublicKeyCredentialRequestOptionsFactory; use Webauthn\PublicKeyCredentialDescriptor; @@ -26,10 +27,21 @@ public function __construct( private readonly SerializerInterface $serializer, private readonly ValidatorInterface $validator, private readonly PublicKeyCredentialUserEntityRepositoryInterface $userEntityRepository, - private readonly PublicKeyCredentialSourceRepository $credentialSourceRepository, + private readonly PublicKeyCredentialSourceRepository|PublicKeyCredentialSourceRepositoryInterface $credentialSourceRepository, private readonly PublicKeyCredentialRequestOptionsFactory $publicKeyCredentialRequestOptionsFactory, private readonly string $profile, ) { + if (! $this->credentialSourceRepository instanceof PublicKeyCredentialSourceRepositoryInterface) { + trigger_deprecation( + 'web-auth/webauthn-symfony-bundle', + '4.6.0', + sprintf( + 'Since 4.6.0, the parameter "$credentialSourceRepository" expects an instance of "%s". Please implement that interface instead of "%s".', + PublicKeyCredentialSourceRepositoryInterface::class, + PublicKeyCredentialSourceRepository::class + ) + ); + } } public function getFromRequest( diff --git a/src/symfony/src/DependencyInjection/Factory/Security/WebauthnFactory.php b/src/symfony/src/DependencyInjection/Factory/Security/WebauthnFactory.php index 22e81ad0..0041716d 100644 --- a/src/symfony/src/DependencyInjection/Factory/Security/WebauthnFactory.php +++ b/src/symfony/src/DependencyInjection/Factory/Security/WebauthnFactory.php @@ -26,6 +26,7 @@ use Webauthn\Bundle\CredentialOptionsBuilder\ProfileBasedCreationOptionsBuilder; use Webauthn\Bundle\CredentialOptionsBuilder\ProfileBasedRequestOptionsBuilder; use Webauthn\Bundle\DependencyInjection\Compiler\DynamicRouteCompilerPass; +use Webauthn\Bundle\Repository\PublicKeyCredentialSourceRepositoryInterface; use Webauthn\Bundle\Repository\PublicKeyCredentialUserEntityRepositoryInterface; use Webauthn\Bundle\Security\Guesser\RequestBodyUserEntityGuesser; use Webauthn\Bundle\Security\Handler\DefaultCreationOptionsHandler; @@ -35,7 +36,6 @@ use Webauthn\Bundle\Security\Storage\SessionStorage; use Webauthn\Bundle\Service\PublicKeyCredentialCreationOptionsFactory; use Webauthn\Bundle\Service\PublicKeyCredentialRequestOptionsFactory; -use Webauthn\PublicKeyCredentialSourceRepository; final class WebauthnFactory implements FirewallListenerFactoryInterface, AuthenticatorFactoryInterface { @@ -466,7 +466,7 @@ private function getAssertionOptionsBuilderId( new Reference(SerializerInterface::class), new Reference(ValidatorInterface::class), new Reference(PublicKeyCredentialUserEntityRepositoryInterface::class), - new Reference(PublicKeyCredentialSourceRepository::class), + new Reference(PublicKeyCredentialSourceRepositoryInterface::class), new Reference(PublicKeyCredentialRequestOptionsFactory::class), $config['profile'], ]); @@ -489,7 +489,7 @@ private function getAttestationOptionsBuilderId( ->setArguments([ new Reference(SerializerInterface::class), new Reference(ValidatorInterface::class), - new Reference(PublicKeyCredentialSourceRepository::class), + new Reference(PublicKeyCredentialSourceRepositoryInterface::class), new Reference(PublicKeyCredentialCreationOptionsFactory::class), $config['profile'], ]); diff --git a/src/symfony/src/DependencyInjection/WebauthnExtension.php b/src/symfony/src/DependencyInjection/WebauthnExtension.php index d7b73299..39234e52 100644 --- a/src/symfony/src/DependencyInjection/WebauthnExtension.php +++ b/src/symfony/src/DependencyInjection/WebauthnExtension.php @@ -37,6 +37,7 @@ use Webauthn\Bundle\DependencyInjection\Compiler\ExtensionOutputCheckerCompilerPass; use Webauthn\Bundle\DependencyInjection\Compiler\LoggerSetterCompilerPass; use Webauthn\Bundle\Doctrine\Type as DbalType; +use Webauthn\Bundle\Repository\PublicKeyCredentialSourceRepositoryInterface; use Webauthn\Bundle\Repository\PublicKeyCredentialUserEntityRepository; use Webauthn\Bundle\Repository\PublicKeyCredentialUserEntityRepositoryInterface; use Webauthn\Bundle\Service\PublicKeyCredentialCreationOptionsFactory; @@ -92,6 +93,7 @@ public function load(array $configs, ContainerBuilder $container): void $container->setAlias('webauthn.logger', $config['logger']); $container->setAlias(PublicKeyCredentialSourceRepository::class, $config['credential_repository']); + $container->setAlias(PublicKeyCredentialSourceRepositoryInterface::class, $config['credential_repository']); $container->setAlias(PublicKeyCredentialUserEntityRepository::class, $config['user_repository']); $container->setAlias(PublicKeyCredentialUserEntityRepositoryInterface::class, $config['user_repository']); @@ -184,7 +186,7 @@ private function loadCreationControllersSupport(ContainerBuilder $container, arr ->setArguments([ new Reference(SerializerInterface::class), new Reference(ValidatorInterface::class), - new Reference(PublicKeyCredentialSourceRepository::class), + new Reference(PublicKeyCredentialSourceRepositoryInterface::class), new Reference(PublicKeyCredentialCreationOptionsFactory::class), $creationConfig['profile'], ]); @@ -245,7 +247,7 @@ private function loadRequestControllersSupport(ContainerBuilder $container, arra new Reference(SerializerInterface::class), new Reference(ValidatorInterface::class), new Reference(PublicKeyCredentialUserEntityRepositoryInterface::class), - new Reference(PublicKeyCredentialSourceRepository::class), + new Reference(PublicKeyCredentialSourceRepositoryInterface::class), new Reference(PublicKeyCredentialRequestOptionsFactory::class), $requestConfig['profile'], ]); diff --git a/src/symfony/src/Exception/HttpNotImplementedException.php b/src/symfony/src/Exception/HttpNotImplementedException.php new file mode 100644 index 00000000..1684a691 --- /dev/null +++ b/src/symfony/src/Exception/HttpNotImplementedException.php @@ -0,0 +1,19 @@ + $headers + */ + public function __construct(string $message = '', Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(501, $message, $previous, $headers, $code); + } +} diff --git a/src/symfony/src/Exception/MissingFeatureException.php b/src/symfony/src/Exception/MissingFeatureException.php new file mode 100644 index 00000000..b917fc29 --- /dev/null +++ b/src/symfony/src/Exception/MissingFeatureException.php @@ -0,0 +1,16 @@ +getManagerForClass($class); + $manager instanceof EntityManagerInterface || throw new RuntimeException(sprintf( + 'Could not find the entity manager for class "%s". Check your Doctrine configuration to make sure it is configured to load this entity\'s metadata.', + $class + )); + $this->class = $class; + $this->manager = $manager; + } + + public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource): void + { + $this->manager->persist($publicKeyCredentialSource); + $this->manager->flush(); + } + + /** + * {@inheritdoc} + */ + public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array + { + $qb = $this->manager->createQueryBuilder(); + + return $qb->select('c') + ->from($this->getClass(), 'c') + ->where('c.userHandle = :userHandle') + ->setParameter(':userHandle', $publicKeyCredentialUserEntity->getId()) + ->getQuery() + ->execute(); + } + + public function findOneByCredentialId(string $publicKeyCredentialId): ?PublicKeyCredentialSource + { + $qb = $this->manager->createQueryBuilder(); + + return $qb->select('c') + ->from($this->getClass(), 'c') + ->where('c.publicKeyCredentialId = :publicKeyCredentialId') + ->setParameter(':publicKeyCredentialId', base64_encode($publicKeyCredentialId)) + ->setMaxResults(1) + ->getQuery() + ->getOneOrNullResult(); + } + + protected function getClass(): string + { + return $this->class; + } + + protected function getEntityManager(): EntityManagerInterface + { + return $this->manager; + } +} diff --git a/src/symfony/src/Repository/DummyPublicKeyCredentialSourceRepository.php b/src/symfony/src/Repository/DummyPublicKeyCredentialSourceRepository.php index 60d4dddc..5e9fb013 100644 --- a/src/symfony/src/Repository/DummyPublicKeyCredentialSourceRepository.php +++ b/src/symfony/src/Repository/DummyPublicKeyCredentialSourceRepository.php @@ -9,14 +9,13 @@ use RuntimeException; use Webauthn\MetadataService\CanLogData; use Webauthn\PublicKeyCredentialSource; -use Webauthn\PublicKeyCredentialSourceRepository; use Webauthn\PublicKeyCredentialUserEntity; /** * This dummy Public Key Credential Source Repository is set to allow the bundle to be installed even if the real * repository is not set in the configuration file. This class shall be replaced in favour of your own implementation. */ -class DummyPublicKeyCredentialSourceRepository implements PublicKeyCredentialSourceRepository, CanLogData +class DummyPublicKeyCredentialSourceRepository implements PublicKeyCredentialSourceRepositoryInterface, CanLogData { public function __construct( private LoggerInterface $logger = new NullLogger() @@ -28,16 +27,6 @@ public function setLogger(LoggerInterface $logger): void $this->logger = $logger; } - public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource): void - { - $this->logger->critical( - 'Please change the Public Key Credential Source Repository in the bundle configuration. See https://webauthn-doc.spomky-labs.com/the-webauthn-server/the-symfony-way#repositories-1' - ); - throw new RuntimeException( - 'You are using the DummyPublicKeyCredentialSourceRepository service. Please create your own repository' - ); - } - /** * {@inheritdoc} */ diff --git a/src/symfony/src/Repository/PublicKeyCredentialSourceRepository.php b/src/symfony/src/Repository/PublicKeyCredentialSourceRepository.php index b206889a..8b9840a2 100644 --- a/src/symfony/src/Repository/PublicKeyCredentialSourceRepository.php +++ b/src/symfony/src/Repository/PublicKeyCredentialSourceRepository.php @@ -4,76 +4,11 @@ namespace Webauthn\Bundle\Repository; -use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepositoryInterface; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\Persistence\ManagerRegistry; -use RuntimeException; -use Webauthn\PublicKeyCredentialSource; use Webauthn\PublicKeyCredentialSourceRepository as PublicKeyCredentialSourceRepositoryInterface; -use Webauthn\PublicKeyCredentialUserEntity; -class PublicKeyCredentialSourceRepository implements PublicKeyCredentialSourceRepositoryInterface, ServiceEntityRepositoryInterface +/** + * @deprecated since 4.6.0, to be removed in 5.0.0. Use Webauthn\Bundle\Repository\DoctrineCredentialSourceRepository instead. + */ +class PublicKeyCredentialSourceRepository extends DoctrineCredentialSourceRepository implements PublicKeyCredentialSourceRepositoryInterface { - private readonly EntityManagerInterface $manager; - - private readonly string $class; - - public function __construct(ManagerRegistry $registry, string $class) - { - is_subclass_of($class, PublicKeyCredentialSource::class) || throw new RuntimeException(sprintf( - 'Invalid class. Must be an instance of "Webauthn\PublicKeyCredentialSource", got "%s" instead.', - $class - )); - $manager = $registry->getManagerForClass($class); - $manager instanceof EntityManagerInterface || throw new RuntimeException(sprintf( - 'Could not find the entity manager for class "%s". Check your Doctrine configuration to make sure it is configured to load this entity\'s metadata.', - $class - )); - $this->class = $class; - $this->manager = $manager; - } - - public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource): void - { - $this->manager->persist($publicKeyCredentialSource); - $this->manager->flush(); - } - - /** - * {@inheritdoc} - */ - public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array - { - $qb = $this->manager->createQueryBuilder(); - - return $qb->select('c') - ->from($this->getClass(), 'c') - ->where('c.userHandle = :userHandle') - ->setParameter(':userHandle', $publicKeyCredentialUserEntity->getId()) - ->getQuery() - ->execute(); - } - - public function findOneByCredentialId(string $publicKeyCredentialId): ?PublicKeyCredentialSource - { - $qb = $this->manager->createQueryBuilder(); - - return $qb->select('c') - ->from($this->getClass(), 'c') - ->where('c.publicKeyCredentialId = :publicKeyCredentialId') - ->setParameter(':publicKeyCredentialId', base64_encode($publicKeyCredentialId)) - ->setMaxResults(1) - ->getQuery() - ->getOneOrNullResult(); - } - - protected function getClass(): string - { - return $this->class; - } - - protected function getEntityManager(): EntityManagerInterface - { - return $this->manager; - } } diff --git a/src/symfony/src/Repository/PublicKeyCredentialSourceRepositoryInterface.php b/src/symfony/src/Repository/PublicKeyCredentialSourceRepositoryInterface.php new file mode 100644 index 00000000..b8f25f0a --- /dev/null +++ b/src/symfony/src/Repository/PublicKeyCredentialSourceRepositoryInterface.php @@ -0,0 +1,18 @@ +services() @@ -28,7 +28,7 @@ service(PublicKeyCredentialCreationOptionsFactory::class), service(PublicKeyCredentialLoader::class), service(AuthenticatorAttestationResponseValidator::class), - service(PublicKeyCredentialSourceRepository::class), + service(PublicKeyCredentialSourceRepositoryInterface::class), ]); $container->set(DefaultFailureHandler::class); $container->set(DefaultSuccessHandler::class); diff --git a/src/symfony/src/Resources/config/security.php b/src/symfony/src/Resources/config/security.php index 83bda86a..251cd451 100644 --- a/src/symfony/src/Resources/config/security.php +++ b/src/symfony/src/Resources/config/security.php @@ -12,6 +12,7 @@ use Webauthn\AuthenticatorAssertionResponseValidator; use Webauthn\AuthenticatorAttestationResponseValidator; use Webauthn\Bundle\DependencyInjection\Factory\Security\WebauthnFactory; +use Webauthn\Bundle\Repository\PublicKeyCredentialSourceRepositoryInterface; use Webauthn\Bundle\Repository\PublicKeyCredentialUserEntityRepositoryInterface; use Webauthn\Bundle\Security\Authorization\Voter\IsUserPresentVoter; use Webauthn\Bundle\Security\Authorization\Voter\IsUserVerifiedVoter; @@ -26,7 +27,6 @@ use Webauthn\Bundle\Security\Storage\SessionStorage; use Webauthn\Bundle\Security\WebauthnFirewallConfig; use Webauthn\PublicKeyCredentialLoader; -use Webauthn\PublicKeyCredentialSourceRepository; return static function (ContainerConfigurator $container): void { $container = $container->services() @@ -44,9 +44,9 @@ $container->set(WebauthnFactory::AUTHENTICATOR_DEFINITION_ID, WebauthnAuthenticator::class)->abstract()->args( [abstract_arg('Firewall config'), abstract_arg('User provider'), abstract_arg('Success handler'), abstract_arg( 'Failure handler' - ), abstract_arg( - 'Options Storage' - ), abstract_arg('Secured Relying Party IDs'), service(PublicKeyCredentialSourceRepository::class), service( + ), abstract_arg('Options Storage'), abstract_arg('Secured Relying Party IDs'), service( + PublicKeyCredentialSourceRepositoryInterface::class + ), service( PublicKeyCredentialUserEntityRepositoryInterface::class ), service(PublicKeyCredentialLoader::class), service( AuthenticatorAssertionResponseValidator::class diff --git a/src/symfony/src/Resources/config/services.php b/src/symfony/src/Resources/config/services.php index 8d76f775..c24a5275 100644 --- a/src/symfony/src/Resources/config/services.php +++ b/src/symfony/src/Resources/config/services.php @@ -49,7 +49,7 @@ ->set(AuthenticatorAttestationResponseValidator::class) ->args([ service(AttestationStatementSupportManager::class), - service(PublicKeyCredentialSourceRepository::class), + null, service(TokenBindingHandler::class)->nullOnInvalid(), service(ExtensionOutputCheckerHandler::class), ]) @@ -58,7 +58,7 @@ ->set(AuthenticatorAssertionResponseValidator::class) ->class(AuthenticatorAssertionResponseValidator::class) ->args([ - service(PublicKeyCredentialSourceRepository::class), + null, service(TokenBindingHandler::class)->nullOnInvalid(), service(ExtensionOutputCheckerHandler::class), service('webauthn.cose.algorithm.manager'), @@ -125,7 +125,7 @@ service(PublicKeyCredentialCreationOptionsFactory::class), service(PublicKeyCredentialLoader::class), service(AuthenticatorAttestationResponseValidator::class), - service(PublicKeyCredentialSourceRepository::class), + service(PublicKeyCredentialSourceRepository::class)->nullOnInvalid(), ]); $container ->set(AssertionControllerFactory::class) @@ -136,7 +136,7 @@ service(PublicKeyCredentialLoader::class), service(AuthenticatorAssertionResponseValidator::class), service(PublicKeyCredentialUserEntityRepositoryInterface::class), - service(PublicKeyCredentialSourceRepository::class), + service(PublicKeyCredentialSourceRepository::class)->nullOnInvalid(), ]); $container diff --git a/src/symfony/src/Security/Http/Authenticator/WebauthnAuthenticator.php b/src/symfony/src/Security/Http/Authenticator/WebauthnAuthenticator.php index da2b6243..83d8de6a 100644 --- a/src/symfony/src/Security/Http/Authenticator/WebauthnAuthenticator.php +++ b/src/symfony/src/Security/Http/Authenticator/WebauthnAuthenticator.php @@ -4,7 +4,6 @@ namespace Webauthn\Bundle\Security\Http\Authenticator; -use LogicException; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; use Symfony\Component\HttpFoundation\Request; @@ -23,13 +22,18 @@ use Webauthn\AuthenticatorAssertionResponseValidator; use Webauthn\AuthenticatorAttestationResponse; use Webauthn\AuthenticatorAttestationResponseValidator; +use Webauthn\Bundle\Exception\HttpNotImplementedException; +use Webauthn\Bundle\Exception\MissingFeatureException; use Webauthn\Bundle\Exception\MissingUserEntityException; use Webauthn\Bundle\Repository\CanRegisterUserEntity; +use Webauthn\Bundle\Repository\CanSaveCredentialSource; +use Webauthn\Bundle\Repository\PublicKeyCredentialSourceRepositoryInterface; use Webauthn\Bundle\Repository\PublicKeyCredentialUserEntityRepositoryInterface; use Webauthn\Bundle\Security\Authentication\Token\WebauthnToken; use Webauthn\Bundle\Security\Http\Authenticator\Passport\Credentials\WebauthnCredentials; use Webauthn\Bundle\Security\Storage\OptionsStorage; use Webauthn\Bundle\Security\WebauthnFirewallConfig; +use Webauthn\Exception\AuthenticatorResponseVerificationException; use Webauthn\Exception\InvalidDataException; use Webauthn\MetadataService\CanLogData; use Webauthn\PublicKeyCredentialCreationOptions; @@ -52,12 +56,23 @@ public function __construct( private readonly AuthenticationFailureHandlerInterface $failureHandler, private readonly OptionsStorage $optionsStorage, private readonly array $securedRelyingPartyIds, - private readonly PublicKeyCredentialSourceRepository $credentialSourceRepository, + private readonly PublicKeyCredentialSourceRepository|PublicKeyCredentialSourceRepositoryInterface $publicKeyCredentialSourceRepository, private readonly PublicKeyCredentialUserEntityRepositoryInterface $credentialUserEntityRepository, private readonly PublicKeyCredentialLoader $publicKeyCredentialLoader, private readonly AuthenticatorAssertionResponseValidator $assertionResponseValidator, private readonly AuthenticatorAttestationResponseValidator $attestationResponseValidator ) { + if (! $this->publicKeyCredentialSourceRepository instanceof PublicKeyCredentialSourceRepositoryInterface) { + trigger_deprecation( + 'web-auth/webauthn-symfony-bundle', + '4.6.0', + sprintf( + 'Since 4.6.0, the parameter "$publicKeyCredentialSourceRepository" expects an instance of "%s". Please implement that interface instead of "%s".', + PublicKeyCredentialSourceRepositoryInterface::class, + PublicKeyCredentialSourceRepository::class + ) + ); + } $this->logger = new NullLogger(); } @@ -176,15 +191,27 @@ private function processWithAssertion(Request $request): Passport 'Invalid data' ); $userEntity = $data->getPublicKeyCredentialUserEntity(); - $source = $this->assertionResponseValidator->check( - $publicKeyCredential->getRawId(), + + $publicKeyCredentialSource = $this->publicKeyCredentialSourceRepository->findOneByCredentialId( + $publicKeyCredential->getRawId() + ); + $publicKeyCredentialSource !== null || throw AuthenticatorResponseVerificationException::create( + 'The credential ID is invalid.' + ); + $publicKeyCredentialSource = $this->assertionResponseValidator->check( + $publicKeyCredentialSource, $response, $publicKeyCredentialRequestOptions, $request->getHost(), $userEntity?->getId(), $this->securedRelyingPartyIds ); - $userEntity = $this->credentialUserEntityRepository->findOneByUserHandle($source->getUserHandle()); + if ($this->publicKeyCredentialSourceRepository instanceof CanSaveCredentialSource) { + $this->publicKeyCredentialSourceRepository->saveCredentialSource($publicKeyCredentialSource); + } + $userEntity = $this->credentialUserEntityRepository->findOneByUserHandle( + $publicKeyCredentialSource->getUserHandle() + ); $userEntity instanceof PublicKeyCredentialUserEntity || throw InvalidDataException::create( $userEntity, 'Invalid user entity' @@ -193,7 +220,7 @@ private function processWithAssertion(Request $request): Passport $response, $publicKeyCredentialRequestOptions, $userEntity, - $source, + $publicKeyCredentialSource, $this->firewallConfig->getFirewallName() ); $userBadge = new UserBadge($userEntity->getName(), $this->userProvider->loadUserByIdentifier(...)); @@ -205,10 +232,13 @@ private function processWithAssertion(Request $request): Passport private function processWithAttestation(Request $request): Passport { - if (! $this->credentialUserEntityRepository instanceof CanRegisterUserEntity) { - throw new LogicException('The credential source repository must implement CanRegisterUserEntity'); - } try { + if (! $this->credentialUserEntityRepository instanceof CanRegisterUserEntity) { + throw MissingFeatureException::create('Unable to register the user.'); + } + if (! $this->publicKeyCredentialSourceRepository instanceof CanSaveCredentialSource) { + throw MissingFeatureException::create('Unable to register the credential.'); + } $format = method_exists( $request, 'getContentTypeFormat' @@ -241,13 +271,13 @@ private function processWithAttestation(Request $request): Passport if ($this->credentialUserEntityRepository->findOneByUsername($userEntity->getName()) !== null) { throw InvalidDataException::create($userEntity, 'The username already exists'); } - if ($this->credentialSourceRepository->findOneByCredentialId( + if ($this->publicKeyCredentialSourceRepository->findOneByCredentialId( $credentialSource->getPublicKeyCredentialId() ) !== null) { throw InvalidDataException::create($credentialSource, 'The credentials already exists'); } $this->credentialUserEntityRepository->saveUserEntity($userEntity); - $this->credentialSourceRepository->saveCredentialSource($credentialSource); + $this->publicKeyCredentialSourceRepository->saveCredentialSource($credentialSource); $credentials = new WebauthnCredentials( $response, $publicKeyCredentialCreationOptions, @@ -258,6 +288,9 @@ private function processWithAttestation(Request $request): Passport $userBadge = new UserBadge($userEntity->getName(), $this->userProvider->loadUserByIdentifier(...)); return new Passport($userBadge, $credentials, []); } catch (Throwable $e) { + if ($e instanceof MissingFeatureException) { + throw new HttpNotImplementedException($e->getMessage(), $e); + } throw new AuthenticationException($e->getMessage(), $e->getCode(), $e); } } diff --git a/src/symfony/src/Service/AuthenticatorAssertionResponseValidator.php b/src/symfony/src/Service/AuthenticatorAssertionResponseValidator.php index 8dce54a1..3a22e788 100644 --- a/src/symfony/src/Service/AuthenticatorAssertionResponseValidator.php +++ b/src/symfony/src/Service/AuthenticatorAssertionResponseValidator.php @@ -15,13 +15,11 @@ use Webauthn\Bundle\Event\AuthenticatorAssertionResponseValidationSucceededEvent; use Webauthn\PublicKeyCredentialRequestOptions; use Webauthn\PublicKeyCredentialSource; -use Webauthn\PublicKeyCredentialSourceRepository; use Webauthn\TokenBinding\TokenBindingHandler; final class AuthenticatorAssertionResponseValidator extends BaseAuthenticatorAssertionResponseValidator { public function __construct( - PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository, ?TokenBindingHandler $tokenBindingHandler, ExtensionOutputCheckerHandler $extensionOutputCheckerHandler, ?Manager $algorithmManager, @@ -36,11 +34,11 @@ public function __construct( BaseAuthenticatorAssertionResponseValidator::class ) ); - parent::__construct($publicKeyCredentialSourceRepository, $tokenBindingHandler, $extensionOutputCheckerHandler, $algorithmManager, $eventDispatcher); + parent::__construct(null, $tokenBindingHandler, $extensionOutputCheckerHandler, $algorithmManager, $eventDispatcher); } protected function createAuthenticatorAssertionResponseValidationSucceededEvent( - string $credentialId, + null|string $credentialId, AuthenticatorAssertionResponse $authenticatorAssertionResponse, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ServerRequestInterface|string $request, diff --git a/src/symfony/src/Service/AuthenticatorAttestationResponseValidator.php b/src/symfony/src/Service/AuthenticatorAttestationResponseValidator.php index 3dfa3514..1e73d059 100644 --- a/src/symfony/src/Service/AuthenticatorAttestationResponseValidator.php +++ b/src/symfony/src/Service/AuthenticatorAttestationResponseValidator.php @@ -15,14 +15,12 @@ use Webauthn\Event\AuthenticatorAttestationResponseValidationFailedEvent; use Webauthn\PublicKeyCredentialCreationOptions; use Webauthn\PublicKeyCredentialSource; -use Webauthn\PublicKeyCredentialSourceRepository; use Webauthn\TokenBinding\TokenBindingHandler; final class AuthenticatorAttestationResponseValidator extends BaseAuthenticatorAttestationResponseValidator { public function __construct( AttestationStatementSupportManager $attestationStatementSupportManager, - PublicKeyCredentialSourceRepository $publicKeyCredentialSource, ?TokenBindingHandler $tokenBindingHandler, ExtensionOutputCheckerHandler $extensionOutputCheckerHandler, ?EventDispatcherInterface $eventDispatcher @@ -36,7 +34,7 @@ public function __construct( BaseAuthenticatorAttestationResponseValidator::class ) ); - parent::__construct($attestationStatementSupportManager, $publicKeyCredentialSource, $tokenBindingHandler, $extensionOutputCheckerHandler, $eventDispatcher); + parent::__construct($attestationStatementSupportManager, null, $tokenBindingHandler, $extensionOutputCheckerHandler, $eventDispatcher); } protected function createAuthenticatorAttestationResponseValidationSucceededEvent( diff --git a/src/webauthn/src/AuthenticatorAssertionResponseValidator.php b/src/webauthn/src/AuthenticatorAssertionResponseValidator.php index a3d16d91..21c35495 100644 --- a/src/webauthn/src/AuthenticatorAssertionResponseValidator.php +++ b/src/webauthn/src/AuthenticatorAssertionResponseValidator.php @@ -44,11 +44,11 @@ class AuthenticatorAssertionResponseValidator implements CanLogData, CanDispatch private EventDispatcherInterface $eventDispatcher; public function __construct( - private readonly PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository, - private readonly ?TokenBindingHandler $tokenBindingHandler, + private readonly null|PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository, + private readonly null|TokenBindingHandler $tokenBindingHandler, private readonly ExtensionOutputCheckerHandler $extensionOutputCheckerHandler, - private readonly ?Manager $algorithmManager, - ?EventDispatcherInterface $eventDispatcher = null, + private readonly null|Manager $algorithmManager, + null|EventDispatcherInterface $eventDispatcher = null, ) { if ($this->tokenBindingHandler !== null) { trigger_deprecation( @@ -57,6 +57,13 @@ public function __construct( 'The parameter "$tokenBindingHandler" is deprecated since 4.3.0 and will be removed in 5.0.0. Please set "null" instead.' ); } + if ($this->publicKeyCredentialSourceRepository !== null) { + trigger_deprecation( + 'web-auth/webauthn-symfony-bundle', + '4.6.0', + 'The parameter "$publicKeyCredentialSourceRepository" is deprecated since 4.6.0 and will be removed in 5.0.0. Please set "null" instead.' + ); + } if ($eventDispatcher === null) { $this->eventDispatcher = new NullEventDispatcher(); } else { @@ -73,11 +80,11 @@ public function __construct( } public static function create( - PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository, - ?TokenBindingHandler $tokenBindingHandler, + null|PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository, + null|TokenBindingHandler $tokenBindingHandler, ExtensionOutputCheckerHandler $extensionOutputCheckerHandler, - ?Manager $algorithmManager, - ?EventDispatcherInterface $eventDispatcher = null + null|Manager $algorithmManager, + null|EventDispatcherInterface $eventDispatcher = null ): self { return new self( $publicKeyCredentialSourceRepository, @@ -94,7 +101,7 @@ public static function create( * @see https://www.w3.org/TR/webauthn/#verifying-assertion */ public function check( - string $credentialId, + string|PublicKeyCredentialSource $credentialId, AuthenticatorAssertionResponse $authenticatorAssertionResponse, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ServerRequestInterface|string $request, @@ -112,6 +119,17 @@ public function check( ) ); } + if (is_string($credentialId)) { + trigger_deprecation( + 'web-auth/webauthn-lib', + '4.6.0', + sprintf( + 'Passing a string as first to the method `check` of the class "%s" is deprecated since 4.6.0. Please inject a %s object instead.', + ServerRequestInterface::class, + PublicKeyCredentialSource::class + ) + ); + } try { $this->logger->info('Checking the authenticator assertion response', [ 'credentialId' => $credentialId, @@ -121,18 +139,18 @@ public function check( ->getHost(), 'userHandle' => $userHandle, ]); + $publicKeyCredentialSource = is_string( + $credentialId + ) ? $this->publicKeyCredentialSourceRepository?->findOneByCredentialId($credentialId) : $credentialId; + $publicKeyCredentialSource !== null || throw AuthenticatorResponseVerificationException::create( + 'The credential ID is invalid.' + ); if (count($publicKeyCredentialRequestOptions->getAllowCredentials()) !== 0) { $this->isCredentialIdAllowed( - $credentialId, + $publicKeyCredentialSource->getPublicKeyCredentialId(), $publicKeyCredentialRequestOptions->getAllowCredentials() ) || throw AuthenticatorResponseVerificationException::create('The credential ID is not allowed.'); } - $publicKeyCredentialSource = $this->publicKeyCredentialSourceRepository->findOneByCredentialId( - $credentialId - ); - $publicKeyCredentialSource !== null || throw AuthenticatorResponseVerificationException::create( - 'The credential ID is invalid.' - ); $attestedCredentialData = $publicKeyCredentialSource->getAttestedCredentialData(); $credentialUserHandle = $publicKeyCredentialSource->getUserHandle(); $responseUserHandle = $authenticatorAssertionResponse->getUserHandle(); @@ -260,7 +278,11 @@ public function check( $this->counterChecker->check($publicKeyCredentialSource, $responseCounter); } $publicKeyCredentialSource->setCounter($responseCounter); - $this->publicKeyCredentialSourceRepository->saveCredentialSource($publicKeyCredentialSource); + if (is_string( + $credentialId + ) && ($this->publicKeyCredentialSourceRepository instanceof PublicKeyCredentialSourceRepository)) { + $this->publicKeyCredentialSourceRepository->saveCredentialSource($publicKeyCredentialSource); + } //All good. We can continue. $this->logger->info('The assertion is valid'); $this->logger->debug('Public Key Credential Source', [ @@ -268,7 +290,7 @@ public function check( ]); $this->eventDispatcher->dispatch( $this->createAuthenticatorAssertionResponseValidationSucceededEvent( - $credentialId, + null, $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, $request, @@ -312,7 +334,7 @@ public function setCounterChecker(CounterChecker $counterChecker): self } protected function createAuthenticatorAssertionResponseValidationSucceededEvent( - string $credentialId, + null|string $credentialId, AuthenticatorAssertionResponse $authenticatorAssertionResponse, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ServerRequestInterface|string $request, diff --git a/src/webauthn/src/AuthenticatorAttestationResponseValidator.php b/src/webauthn/src/AuthenticatorAttestationResponseValidator.php index 0c0929af..b48a81e2 100644 --- a/src/webauthn/src/AuthenticatorAttestationResponseValidator.php +++ b/src/webauthn/src/AuthenticatorAttestationResponseValidator.php @@ -51,10 +51,10 @@ class AuthenticatorAttestationResponseValidator implements CanLogData, CanDispat public function __construct( private readonly AttestationStatementSupportManager $attestationStatementSupportManager, - private readonly PublicKeyCredentialSourceRepository $publicKeyCredentialSource, - private readonly ?TokenBindingHandler $tokenBindingHandler, + private readonly null|PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository, + private readonly null|TokenBindingHandler $tokenBindingHandler, private readonly ExtensionOutputCheckerHandler $extensionOutputCheckerHandler, - ?EventDispatcherInterface $eventDispatcher = null, + null|EventDispatcherInterface $eventDispatcher = null, ) { if ($this->tokenBindingHandler !== null) { trigger_deprecation( @@ -63,6 +63,13 @@ public function __construct( 'The parameter "$tokenBindingHandler" is deprecated since 4.3.0 and will be removed in 5.0.0. Please set "null" instead.' ); } + if ($this->publicKeyCredentialSourceRepository !== null) { + trigger_deprecation( + 'web-auth/webauthn-symfony-bundle', + '4.6.0', + 'The parameter "$publicKeyCredentialSourceRepository" is deprecated since 4.6.0 and will be removed in 5.0.0. Please set "null" instead.' + ); + } if ($eventDispatcher === null) { $this->eventDispatcher = new NullEventDispatcher(); } else { @@ -78,14 +85,14 @@ public function __construct( public static function create( AttestationStatementSupportManager $attestationStatementSupportManager, - PublicKeyCredentialSourceRepository $publicKeyCredentialSource, - ?TokenBindingHandler $tokenBindingHandler, + null|PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository, + null|TokenBindingHandler $tokenBindingHandler, ExtensionOutputCheckerHandler $extensionOutputCheckerHandler, - ?EventDispatcherInterface $eventDispatcher = null + null|EventDispatcherInterface $eventDispatcher = null ): self { return new self( $attestationStatementSupportManager, - $publicKeyCredentialSource, + $publicKeyCredentialSourceRepository, $tokenBindingHandler, $extensionOutputCheckerHandler, $eventDispatcher, @@ -244,11 +251,13 @@ public function check( 'There is no attested credential data.' ); $credentialId = $attestedCredentialData->getCredentialId(); - $this->publicKeyCredentialSource->findOneByCredentialId( - $credentialId - ) === null || throw AuthenticatorResponseVerificationException::create( - 'The credential ID already exists.' - ); + if ($this->publicKeyCredentialSourceRepository !== null) { + $this->publicKeyCredentialSourceRepository->findOneByCredentialId( + $credentialId + ) === null || throw AuthenticatorResponseVerificationException::create( + 'The credential ID already exists.' + ); + } $publicKeyCredentialSource = $this->createPublicKeyCredentialSource( $credentialId, $attestedCredentialData, diff --git a/src/webauthn/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php b/src/webauthn/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php index d05cd9ab..bed31ddd 100644 --- a/src/webauthn/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php +++ b/src/webauthn/src/Event/AuthenticatorAssertionResponseValidationSucceededEvent.php @@ -12,7 +12,7 @@ class AuthenticatorAssertionResponseValidationSucceededEvent { public function __construct( - private readonly string $credentialId, + private readonly null|string $credentialId, private readonly AuthenticatorAssertionResponse $authenticatorAssertionResponse, private readonly PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, public readonly ServerRequestInterface|string $host, @@ -30,11 +30,18 @@ public function __construct( ) ); } + if ($this->credentialId !== null) { + trigger_deprecation( + 'web-auth/webauthn-lib', + '4.6.0', + 'The argument "$credentialId" is deprecated since 4.6.0 and will be removed in 5.0.0. Please set null instead.' + ); + } } public function getCredentialId(): string { - return $this->credentialId; + return $this->publicKeyCredentialSource->getPublicKeyCredentialId(); } public function getAuthenticatorAssertionResponse(): AuthenticatorAssertionResponse diff --git a/src/webauthn/src/PublicKeyCredentialSourceRepository.php b/src/webauthn/src/PublicKeyCredentialSourceRepository.php index 7ab99923..4c553f1e 100644 --- a/src/webauthn/src/PublicKeyCredentialSourceRepository.php +++ b/src/webauthn/src/PublicKeyCredentialSourceRepository.php @@ -4,6 +4,9 @@ namespace Webauthn; +/** + * @deprecated + */ interface PublicKeyCredentialSourceRepository { public function findOneByCredentialId(string $publicKeyCredentialId): ?PublicKeyCredentialSource; diff --git a/tests/framework/MemoryPublicKeyCredentialSourceRepository.php b/tests/framework/MemoryPublicKeyCredentialSourceRepository.php deleted file mode 100644 index 702fe31a..00000000 --- a/tests/framework/MemoryPublicKeyCredentialSourceRepository.php +++ /dev/null @@ -1,32 +0,0 @@ -sources[$publicKeyCredentialId] ?? null; - } - - public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array - { - return []; - } - - public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource): void - { - $this->sources[$publicKeyCredentialSource->getPublicKeyCredentialId()] = $publicKeyCredentialSource; - } -} diff --git a/tests/library/Functional/AbstractTestCase.php b/tests/library/Functional/AbstractTestCase.php index 9ddc4a1a..8f892788 100644 --- a/tests/library/Functional/AbstractTestCase.php +++ b/tests/library/Functional/AbstractTestCase.php @@ -38,7 +38,6 @@ use Webauthn\MetadataService\Service\LocalResourceMetadataService; use Webauthn\MetadataService\Service\StringMetadataService; use Webauthn\PublicKeyCredentialLoader; -use Webauthn\PublicKeyCredentialSourceRepository; use Webauthn\Tests\Bundle\Functional\MockClock; use Webauthn\Tests\MockedPublicKeyCredentialSourceTrait; use Webauthn\Tests\MockedRequestTrait; @@ -83,13 +82,12 @@ protected function getPublicKeyCredentialLoader(): PublicKeyCredentialLoader } protected function getAuthenticatorAttestationResponseValidator( - PublicKeyCredentialSourceRepository $credentialRepository, ?ClientInterface $client = null ): AuthenticatorAttestationResponseValidator { if ($this->authenticatorAttestationResponseValidator === null) { $this->authenticatorAttestationResponseValidator = new AuthenticatorAttestationResponseValidator( $this->getAttestationStatementSupportManager($client), - $credentialRepository, + null, null, new ExtensionOutputCheckerHandler() ); @@ -103,12 +101,11 @@ protected function getAuthenticatorAttestationResponseValidator( return $this->authenticatorAttestationResponseValidator; } - protected function getAuthenticatorAssertionResponseValidator( - PublicKeyCredentialSourceRepository $credentialRepository - ): AuthenticatorAssertionResponseValidator { + protected function getAuthenticatorAssertionResponseValidator(): AuthenticatorAssertionResponseValidator + { if ($this->authenticatorAssertionResponseValidator === null) { $this->authenticatorAssertionResponseValidator = new AuthenticatorAssertionResponseValidator( - $credentialRepository, + null, null, new ExtensionOutputCheckerHandler(), $this->getAlgorithmManager(), diff --git a/tests/library/Functional/AndroidSafetyNetAttestationStatementTest.php b/tests/library/Functional/AndroidSafetyNetAttestationStatementTest.php index 054c3198..5c78e235 100644 --- a/tests/library/Functional/AndroidSafetyNetAttestationStatementTest.php +++ b/tests/library/Functional/AndroidSafetyNetAttestationStatementTest.php @@ -14,7 +14,6 @@ use Webauthn\PublicKeyCredentialParameters; use Webauthn\PublicKeyCredentialRpEntity; use Webauthn\PublicKeyCredentialUserEntity; -use Webauthn\Tests\MemoryPublicKeyCredentialSourceRepository; /** * @internal @@ -40,7 +39,6 @@ public function anExpiredAndroidSafetyNetAttestationCannotBeVerified(): void '{"id":"Ac8zKrpVWv9UCwxY1FyMqkESz2lV4CNwTk2-Hp19LgKbvh5uQ2_i6AMbTbTz1zcNapCEeiLJPlAAVM4L7AIow6I","type":"public-key","rawId":"Ac8zKrpVWv9UCwxY1FyMqkESz2lV4CNwTk2+Hp19LgKbvh5uQ2/i6AMbTbTz1zcNapCEeiLJPlAAVM4L7AIow6I=","response":{"clientDataJSON":"eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoia21uczQzQ1dWc3diTW92cktQa2dkMWxFcGM2TFpkZmswVVFfbnVaYnAwMGpXNUM2MVBFVzFkTmFwdFowR2tySUs5V1J0YUFYV2tuZElFRUJnTklDUnciLCJvcmlnaW4iOiJodHRwczpcL1wvd2ViYXV0aG4ubW9yc2VsbGkuZnIiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uYW5kcm9pZC5jaHJvbWUifQ","attestationObject":"o2NmbXRxYW5kcm9pZC1zYWZldHluZXRnYXR0U3RtdKJjdmVyaDE0Nzk5MDM3aHJlc3BvbnNlWRS9ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbmcxWXlJNld5Sk5TVWxHYTJwRFEwSkljV2RCZDBsQ1FXZEpVVkpZY205T01GcFBaRkpyUWtGQlFVRkJRVkIxYm5wQlRrSm5hM0ZvYTJsSE9YY3dRa0ZSYzBaQlJFSkRUVkZ6ZDBOUldVUldVVkZIUlhkS1ZsVjZSV1ZOUW5kSFFURlZSVU5vVFZaU01qbDJXako0YkVsR1VubGtXRTR3U1VaT2JHTnVXbkJaTWxaNlRWSk5kMFZSV1VSV1VWRkVSWGR3U0ZaR1RXZFJNRVZuVFZVNGVFMUNORmhFVkVVMFRWUkJlRTFFUVROTlZHc3dUbFp2V0VSVVJUVk5WRUYzVDFSQk0wMVVhekJPVm05M1lrUkZURTFCYTBkQk1WVkZRbWhOUTFaV1RYaEZla0ZTUW1kT1ZrSkJaMVJEYTA1b1lrZHNiV0l6U25WaFYwVjRSbXBCVlVKblRsWkNRV05VUkZVeGRtUlhOVEJaVjJ4MVNVWmFjRnBZWTNoRmVrRlNRbWRPVmtKQmIxUkRhMlIyWWpKa2MxcFRRazFVUlUxNFIzcEJXa0puVGxaQ1FVMVVSVzFHTUdSSFZucGtRelZvWW0xU2VXSXliR3RNYlU1MllsUkRRMEZUU1hkRVVWbEtTMjlhU1doMlkwNUJVVVZDUWxGQlJHZG5SVkJCUkVORFFWRnZRMmRuUlVKQlRtcFlhM293WlVzeFUwVTBiU3N2UnpWM1QyOHJXRWRUUlVOeWNXUnVPRGh6UTNCU04yWnpNVFJtU3pCU2FETmFRMWxhVEVaSWNVSnJOa0Z0V2xaM01rczVSa2N3VHpseVVsQmxVVVJKVmxKNVJUTXdVWFZ1VXpsMVowaEROR1ZuT1c5MmRrOXRLMUZrV2pKd09UTllhSHAxYmxGRmFGVlhXRU40UVVSSlJVZEtTek5UTW1GQlpucGxPVGxRVEZNeU9XaE1ZMUYxV1ZoSVJHRkROMDlhY1U1dWIzTnBUMGRwWm5NNGRqRnFhVFpJTDNob2JIUkRXbVV5YkVvck4wZDFkSHBsZUV0d2VIWndSUzkwV2xObVlsazVNRFZ4VTJ4Q2FEbG1jR293TVRWamFtNVJSbXRWYzBGVmQyMUxWa0ZWZFdWVmVqUjBTMk5HU3pSd1pYWk9UR0Y0UlVGc0swOXJhV3hOZEVsWlJHRmpSRFZ1Wld3MGVFcHBlWE0wTVROb1lXZHhWekJYYUdnMVJsQXpPV2hIYXpsRkwwSjNVVlJxWVhwVGVFZGtkbGd3YlRaNFJsbG9hQzh5VmsxNVdtcFVORXQ2VUVwRlEwRjNSVUZCWVU5RFFXeG5kMmRuU2xWTlFUUkhRVEZWWkVSM1JVSXZkMUZGUVhkSlJtOUVRVlJDWjA1V1NGTlZSVVJFUVV0Q1oyZHlRbWRGUmtKUlkwUkJWRUZOUW1kT1ZraFNUVUpCWmpoRlFXcEJRVTFDTUVkQk1WVmtSR2RSVjBKQ1VYRkNVWGRIVjI5S1FtRXhiMVJMY1hWd2J6UlhObmhVTm1veVJFRm1RbWRPVmtoVFRVVkhSRUZYWjBKVFdUQm1hSFZGVDNaUWJTdDRaMjU0YVZGSE5rUnlabEZ1T1V0NlFtdENaMmR5UW1kRlJrSlJZMEpCVVZKWlRVWlpkMHAzV1VsTGQxbENRbEZWU0UxQlIwZEhNbWd3WkVoQk5reDVPWFpaTTA1M1RHNUNjbUZUTlc1aU1qbHVUREprTUdONlJuWk5WRUZ5UW1kbmNrSm5SVVpDVVdOM1FXOVpabUZJVWpCalJHOTJURE5DY21GVE5XNWlNamx1VERKa2VtTnFTWFpTTVZKVVRWVTRlRXh0VG5sa1JFRmtRbWRPVmtoU1JVVkdha0ZWWjJoS2FHUklVbXhqTTFGMVdWYzFhMk50T1hCYVF6VnFZakl3ZDBsUldVUldVakJuUWtKdmQwZEVRVWxDWjFwdVoxRjNRa0ZuU1hkRVFWbExTM2RaUWtKQlNGZGxVVWxHUVhwQmRrSm5UbFpJVWpoRlMwUkJiVTFEVTJkSmNVRm5hR2cxYjJSSVVuZFBhVGgyV1ROS2MweHVRbkpoVXpWdVlqSTVia3d3WkZWVmVrWlFUVk0xYW1OdGQzZG5aMFZGUW1kdmNrSm5SVVZCWkZvMVFXZFJRMEpKU0RGQ1NVaDVRVkJCUVdSM1EydDFVVzFSZEVKb1dVWkpaVGRGTmt4TldqTkJTMUJFVjFsQ1VHdGlNemRxYW1RNE1FOTVRVE5qUlVGQlFVRlhXbVJFTTFCTVFVRkJSVUYzUWtsTlJWbERTVkZEVTFwRFYyVk1Tblp6YVZaWE5rTm5LMmRxTHpsM1dWUktVbnAxTkVocGNXVTBaVmswWXk5dGVYcHFaMGxvUVV4VFlta3ZWR2g2WTNweGRHbHFNMlJyTTNaaVRHTkpWek5NYkRKQ01HODNOVWRSWkdoTmFXZGlRbWRCU0ZWQlZtaFJSMjFwTDFoM2RYcFVPV1ZIT1ZKTVNTdDRNRm95ZFdKNVdrVldla0UzTlZOWlZtUmhTakJPTUVGQlFVWnRXRkU1ZWpWQlFVRkNRVTFCVW1wQ1JVRnBRbU5EZDBFNWFqZE9WRWRZVURJM09IbzBhSEl2ZFVOSWFVRkdUSGx2UTNFeVN6QXJlVXhTZDBwVlltZEpaMlk0WjBocWRuQjNNbTFDTVVWVGFuRXlUMll6UVRCQlJVRjNRMnR1UTJGRlMwWlZlVm8zWmk5UmRFbDNSRkZaU2t0dldrbG9kbU5PUVZGRlRFSlJRVVJuWjBWQ1FVazVibFJtVWt0SlYyZDBiRmRzTTNkQ1REVTFSVlJXTm10aGVuTndhRmN4ZVVGak5VUjFiVFpZVHpReGExcDZkMG8yTVhkS2JXUlNVbFF2VlhORFNYa3hTMFYwTW1Nd1JXcG5iRzVLUTBZeVpXRjNZMFZYYkV4UldUSllVRXg1Um1wclYxRk9ZbE5vUWpGcE5GY3lUbEpIZWxCb2RETnRNV0kwT1doaWMzUjFXRTAyZEZnMVEzbEZTRzVVYURoQ2IyMDBMMWRzUm1sb2VtaG5iamd4Ukd4a2IyZDZMMHN5VlhkTk5sTTJRMEl2VTBWNGEybFdabllyZW1KS01ISnFkbWM1TkVGc1pHcFZabFYzYTBrNVZrNU5ha1ZRTldVNGVXUkNNMjlNYkRabmJIQkRaVVkxWkdkbVUxZzBWVGw0TXpWdmFpOUpTV1F6VlVVdlpGQndZaTl4WjBkMmMydG1aR1Y2ZEcxVmRHVXZTMU50Y21sM1kyZFZWMWRsV0daVVlra3plbk5wYTNkYVltdHdiVkpaUzIxcVVHMW9kalJ5YkdsNlIwTkhkRGhRYmpod2NUaE5Na3RFWmk5UU0ydFdiM1F6WlRFNFVUMGlMQ0pOU1VsRlUycERRMEY2UzJkQmQwbENRV2RKVGtGbFR6QnRjVWRPYVhGdFFrcFhiRkYxUkVGT1FtZHJjV2hyYVVjNWR6QkNRVkZ6UmtGRVFrMU5VMEYzU0dkWlJGWlJVVXhGZUdSSVlrYzVhVmxYZUZSaFYyUjFTVVpLZG1JelVXZFJNRVZuVEZOQ1UwMXFSVlJOUWtWSFFURlZSVU5vVFV0U01uaDJXVzFHYzFVeWJHNWlha1ZVVFVKRlIwRXhWVVZCZUUxTFVqSjRkbGx0Um5OVk1teHVZbXBCWlVaM01IaE9la0V5VFZSVmQwMUVRWGRPUkVwaFJuY3dlVTFVUlhsTlZGVjNUVVJCZDA1RVNtRk5SVWw0UTNwQlNrSm5UbFpDUVZsVVFXeFdWRTFTTkhkSVFWbEVWbEZSUzBWNFZraGlNamx1WWtkVloxWklTakZqTTFGblZUSldlV1J0YkdwYVdFMTRSWHBCVWtKblRsWkNRVTFVUTJ0a1ZWVjVRa1JSVTBGNFZIcEZkMmRuUldsTlFUQkhRMU54UjFOSllqTkVVVVZDUVZGVlFVRTBTVUpFZDBGM1oyZEZTMEZ2U1VKQlVVUlJSMDA1UmpGSmRrNHdOWHByVVU4NUszUk9NWEJKVW5aS2VucDVUMVJJVnpWRWVrVmFhRVF5WlZCRGJuWlZRVEJSYXpJNFJtZEpRMlpMY1VNNVJXdHpRelJVTW1aWFFsbHJMMnBEWmtNelVqTldXazFrVXk5a1RqUmFTME5GVUZwU2NrRjZSSE5wUzFWRWVsSnliVUpDU2pWM2RXUm5lbTVrU1UxWlkweGxMMUpIUjBac05YbFBSRWxMWjJwRmRpOVRTa2d2VlV3clpFVmhiSFJPTVRGQ2JYTkxLMlZSYlUxR0t5dEJZM2hIVG1oeU5UbHhUUzg1YVd3M01Va3laRTQ0UmtkbVkyUmtkM1ZoWldvMFlsaG9jREJNWTFGQ1ltcDRUV05KTjBwUU1HRk5NMVEwU1N0RWMyRjRiVXRHYzJKcWVtRlVUa001ZFhwd1JteG5UMGxuTjNKU01qVjRiM2x1VlhoMk9IWk9iV3R4TjNwa1VFZElXR3Q0VjFrM2IwYzVhaXRLYTFKNVFrRkNhemRZY2twbWIzVmpRbHBGY1VaS1NsTlFhemRZUVRCTVMxY3dXVE42Tlc5Nk1rUXdZekYwU2t0M1NFRm5UVUpCUVVkcVoyZEZlazFKU1VKTWVrRlBRbWRPVmtoUk9FSkJaamhGUWtGTlEwRlpXWGRJVVZsRVZsSXdiRUpDV1hkR1FWbEpTM2RaUWtKUlZVaEJkMFZIUTBOelIwRlJWVVpDZDAxRFRVSkpSMEV4VldSRmQwVkNMM2RSU1UxQldVSkJaamhEUVZGQmQwaFJXVVJXVWpCUFFrSlpSVVpLYWxJclJ6UlJOamdyWWpkSFEyWkhTa0ZpYjA5ME9VTm1NSEpOUWpoSFFURlZaRWwzVVZsTlFtRkJSa3AyYVVJeFpHNUlRamRCWVdkaVpWZGlVMkZNWkM5alIxbFpkVTFFVlVkRFEzTkhRVkZWUmtKM1JVSkNRMnQzU25wQmJFSm5aM0pDWjBWR1FsRmpkMEZaV1ZwaFNGSXdZMFJ2ZGt3eU9XcGpNMEYxWTBkMGNFeHRaSFppTW1OMldqTk9lVTFxUVhsQ1owNVdTRkk0UlV0NlFYQk5RMlZuU21GQmFtaHBSbTlrU0ZKM1QyazRkbGt6U25OTWJrSnlZVk0xYm1JeU9XNU1NbVI2WTJwSmRsb3pUbmxOYVRWcVkyMTNkMUIzV1VSV1VqQm5Ra1JuZDA1cVFUQkNaMXB1WjFGM1FrRm5TWGRMYWtGdlFtZG5ja0puUlVaQ1VXTkRRVkpaWTJGSVVqQmpTRTAyVEhrNWQyRXlhM1ZhTWpsMlduazVlVnBZUW5aak1td3dZak5LTlV4NlFVNUNaMnR4YUd0cFJ6bDNNRUpCVVhOR1FVRlBRMEZSUlVGSGIwRXJUbTV1TnpoNU5uQlNhbVE1V0d4UlYwNWhOMGhVWjJsYUwzSXpVazVIYTIxVmJWbElVRkZ4TmxOamRHazVVRVZoYW5aM1VsUXlhVmRVU0ZGeU1ESm1aWE54VDNGQ1dUSkZWRlYzWjFwUksyeHNkRzlPUm5ab2MwODVkSFpDUTA5SllYcHdjM2RYUXpsaFNqbDRhblUwZEZkRVVVZzRUbFpWTmxsYVdpOVlkR1ZFVTBkVk9WbDZTbkZRYWxrNGNUTk5SSGh5ZW0xeFpYQkNRMlkxYnpodGR5OTNTalJoTWtjMmVIcFZjalpHWWpaVU9FMWpSRTh5TWxCTVVrdzJkVE5OTkZSNmN6TkJNazB4YWpaaWVXdEtXV2s0ZDFkSlVtUkJka3RNVjFwMUwyRjRRbFppZWxsdGNXMTNhMjAxZWt4VFJGYzFia2xCU21KRlRFTlJRMXAzVFVnMU5uUXlSSFp4YjJaNGN6WkNRbU5EUmtsYVZWTndlSFUyZURaMFpEQldOMU4yU2tORGIzTnBjbE50U1dGMGFpODVaRk5UVmtSUmFXSmxkRGh4THpkVlN6UjJORnBWVGpnd1lYUnVXbm94ZVdjOVBTSmRmUS5leUp1YjI1alpTSTZJbVoxUlZsb0szaFhVRkEzZUhCNVVUZzVhbGh3Y0ZGT05tMWlNV2RYWnpNM1JsQnZOM05VU2pFeFVFMDlJaXdpZEdsdFpYTjBZVzF3VFhNaU9qRTFORGcwT0RneU5UazRNamtzSW1Gd2ExQmhZMnRoWjJWT1lXMWxJam9pWTI5dExtZHZiMmRzWlM1aGJtUnliMmxrTG1kdGN5SXNJbUZ3YTBScFoyVnpkRk5vWVRJMU5pSTZJa0YyV0hGcE1FSnRiVXRKYm1KSVlqTXlaalI2VldoMmVqUmxjR3BwU25RM2EwdE5SMmhUZDNjeFJGVTlJaXdpWTNSelVISnZabWxzWlUxaGRHTm9JanAwY25WbExDSmhjR3REWlhKMGFXWnBZMkYwWlVScFoyVnpkRk5vWVRJMU5pSTZXeUk0VURGelZ6QkZVRXBqYzJ4M04xVjZVbk5wV0V3Mk5IY3JUelV3UldRclVrSkpRM1JoZVRGbk1qUk5QU0pkTENKaVlYTnBZMGx1ZEdWbmNtbDBlU0k2ZEhKMVpYMC5DQldQQ1FNaDBIdjhSTllZc05HTGVuci16RVEyY3o2Q25xalZhblZKOXV1b0d5WFpkc19mRTkwbFRjN0tpYVFMNExWSDl1TnNLWjdyN0xZSzRHTHhHekNqWklwZFlFZUIwdWxaWEN1bDdaVFI2MzZmODBWZmxkZ0dJdDRocWJ6S3dsd0EwNEZJN3ZpbDZjbkNJRHQ4SHVyTzVwRnJIdDVhUkpVcUxnOWhPT3VOaDVYS1JQS29aVTZyQlg5eVhxUmFtbl9SbWd6SkEwRGpqcXNaM3BlYUVvX2g5T0hJUHV3Q3FXZUdlZk5lRmoxVnBnaENpdW1lMXpPb2lwSmt3Tkx3dHdJamNDZ0VqYmc1OEF6ZHBPY01fLUtKYXBUeFJlYk9ZclM3dExTUlZfb2xjZG9PWGUtZ0ctVktCeTRUclJkdE9zNUdydTBqdlNyUGMwZXh6OHV2MkFoYXV0aERhdGFYxcrUbtuZYVMj5mIkvf6KvF1ZzC0gYwKd4+myQgSJCUO2RQAAAAC5P9lh8uZGL7EiggAiR954AEEBzzMqulVa/1QLDFjUXIyqQRLPaVXgI3BOTb4enX0uApu+Hm5Db+LoAxtNtPPXNw1qkIR6Isk+UABUzgvsAijDoqUBAgMmIAEhWCACJyweJ5aGUeFWycOhX/jCeAcTVjAxnbZnJmxj+aLWtyJYIAOY6jc/2y5iT60VYTtZaeBvsQIwgU/XR9Fax7xtatkY"}}' ); static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse()); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); $client = new Client(); $httpResponse = new Response(); $httpResponse = $httpResponse->withHeader('content-type', 'application/json'); @@ -49,7 +47,7 @@ public function anExpiredAndroidSafetyNetAttestationCannotBeVerified(): void $httpResponse->getBody() ->rewind(); $client->setDefaultResponse($httpResponse); - $this->getAuthenticatorAttestationResponseValidator($credentialRepository, $client) + $this->getAuthenticatorAttestationResponseValidator($client) ->check($publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, 'webauthn.morselli.fr'); } } diff --git a/tests/library/Functional/AppleAttestationStatementTest.php b/tests/library/Functional/AppleAttestationStatementTest.php index bde164a7..5b7c369b 100644 --- a/tests/library/Functional/AppleAttestationStatementTest.php +++ b/tests/library/Functional/AppleAttestationStatementTest.php @@ -17,7 +17,6 @@ use Webauthn\PublicKeyCredentialParameters; use Webauthn\PublicKeyCredentialRpEntity; use Webauthn\PublicKeyCredentialUserEntity; -use Webauthn\Tests\MemoryPublicKeyCredentialSourceRepository; /** * @internal @@ -45,8 +44,7 @@ public function anAppleAttestationCanBeVerified(): void "type": "public-key" }'); static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse()); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $this->getAuthenticatorAttestationResponseValidator($credentialRepository) + $this->getAuthenticatorAttestationResponseValidator() ->check($publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, 'dev.dontneeda.pw'); $publicKeyCredentialDescriptor = $publicKeyCredential->getPublicKeyCredentialDescriptor(['usb']); static::assertSame( diff --git a/tests/library/Functional/AssertionTest.php b/tests/library/Functional/AssertionTest.php index 293ceb6c..b17b0257 100644 --- a/tests/library/Functional/AssertionTest.php +++ b/tests/library/Functional/AssertionTest.php @@ -10,7 +10,6 @@ use Webauthn\AuthenticatorAssertionResponse; use Webauthn\PublicKeyCredentialDescriptor; use Webauthn\PublicKeyCredentialRequestOptions; -use Webauthn\Tests\MemoryPublicKeyCredentialSourceRepository; /** * @internal @@ -52,11 +51,9 @@ public function anAssertionCanBeVerified(): void true ) ); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $credentialRepository->saveCredentialSource($publicKeyCredentialSource); - $this->getAuthenticatorAssertionResponseValidator($credentialRepository) + $publicKeyCredentialSource = $this->getAuthenticatorAssertionResponseValidator() ->check( - $publicKeyCredential->getRawId(), + $publicKeyCredentialSource, $publicKeyCredential->getResponse(), $publicKeyCredentialRequestOptions, 'localhost', @@ -101,11 +98,9 @@ public function anAssertionWithTokenBindingCanBeVerified(): void true ) ); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $credentialRepository->saveCredentialSource($publicKeyCredentialSource); - $this->getAuthenticatorAssertionResponseValidator($credentialRepository) + $publicKeyCredentialSource = $this->getAuthenticatorAssertionResponseValidator() ->check( - $publicKeyCredential->getRawId(), + $publicKeyCredentialSource, $publicKeyCredential->getResponse(), $publicKeyCredentialRequestOptions, 'localhost', @@ -150,11 +145,9 @@ public function anAssertionWithUserHandleCanBeVerified(): void true ) ); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $credentialRepository->saveCredentialSource($publicKeyCredentialSource); - $this->getAuthenticatorAssertionResponseValidator($credentialRepository) + $publicKeyCredentialSource = $this->getAuthenticatorAssertionResponseValidator() ->check( - $publicKeyCredential->getRawId(), + $publicKeyCredentialSource, $publicKeyCredential->getResponse(), $publicKeyCredentialRequestOptions, 'spomky-webauthn.herokuapp.com', diff --git a/tests/library/Functional/AttestationStatementWithTokenBindingTest.php b/tests/library/Functional/AttestationStatementWithTokenBindingTest.php index a14f8b35..a2ce483c 100644 --- a/tests/library/Functional/AttestationStatementWithTokenBindingTest.php +++ b/tests/library/Functional/AttestationStatementWithTokenBindingTest.php @@ -15,7 +15,6 @@ use Webauthn\PublicKeyCredentialParameters; use Webauthn\PublicKeyCredentialRpEntity; use Webauthn\PublicKeyCredentialUserEntity; -use Webauthn\Tests\MemoryPublicKeyCredentialSourceRepository; /** * @internal @@ -39,8 +38,7 @@ public function anAttestationWithTokenBindingCanBeVerified(): void '{"id":"-uZVS9-4JgjAYI49YhdzTgHmbn638-ZNSvC0UtHkWTVS-CtTjnaSbqtzdzijByOAvEAsh-TaQJAr43FRj-dYag","type":"public-key","rawId":"+uZVS9+4JgjAYI49YhdzTgHmbn638+ZNSvC0UtHkWTVS+CtTjnaSbqtzdzijByOAvEAsh+TaQJAr43FRj+dYag==","response":{"clientDataJSON":"ew0KCSJ0eXBlIiA6ICJ3ZWJhdXRobi5jcmVhdGUiLA0KCSJjaGFsbGVuZ2UiIDogIlNrZWhNb0FrR3YtY3FtdWlFcXBPZ0doc3dqNW9EYTlrSVB4Z0cxSWloemt4UGU0TE5mUDhiVXlGaU5uX01YQmxxaU9ZNklwSEZabDFYZklNMDdrUlp3IiwNCgkib3JpZ2luIiA6ICJodHRwczovL3dlYmF1dGhuLm1vcnNlbGxpLmZyIiwNCgkidG9rZW5CaW5kaW5nIiA6IA0KCXsNCgkJInN0YXR1cyIgOiAic3VwcG9ydGVkIg0KCX0NCn0","attestationObject":"o2NmbXRmcGFja2VkaGF1dGhEYXRhWMTK1G7bmWFTI+ZiJL3+irxdWcwtIGMCnePpskIEiQlDtkUAAACS+KAR84wKTRWABhcRH57cfQBA+uZVS9+4JgjAYI49YhdzTgHmbn638+ZNSvC0UtHkWTVS+CtTjnaSbqtzdzijByOAvEAsh+TaQJAr43FRj+dYaqUBAgMmIAEhWCBghVX3//iILN98CBMBKcKrotdlzBdLaH/Hg88GTQV/HiJYIHJsHBPRfVuaLrsZcyiWxCSMZlJZkR7wZMg4a6oZ+zacZ2F0dFN0bXSjY2FsZyZjc2lnWEcwRQIgF/4vvqanyO+5+IHsw8GbSWh+qLHbejybS9K7mpIhR/ACIQCMImx8JpQjbCXrXxwJ1uUnwQcTXBVU3+luI56lJ+S9kGN4NWOBWQLCMIICvjCCAaagAwIBAgIEdIb9wjANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbzELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTk1NTAwMzg0MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJVd8633JH0xde/9nMTzGk6HjrrhgQlWYVD7OIsuX2Unv1dAmqWBpQ0KxS8YRFwKE1SKE1PIpOWacE5SO8BN6+2jbDBqMCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS4xMBMGCysGAQQBguUcAgEBBAQDAgUgMCEGCysGAQQBguUcAQEEBBIEEPigEfOMCk0VgAYXER+e3H0wDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAMVxIgOaaUn44Zom9af0KqG9J655OhUVBVW+q0As6AIod3AH5bHb2aDYakeIyyBCnnGMHTJtuekbrHbXYXERIn4aKdkPSKlyGLsA/A+WEi+OAfXrNVfjhrh7iE6xzq0sg4/vVJoywe4eAJx0fS+Dl3axzTTpYl71Nc7p/NX6iCMmdik0pAuYJegBcTckE3AoYEg4K99AM/JaaKIblsbFh8+3LxnemeNf7UwOczaGGvjS6UzGVI0Odf9lKcPIwYhuTxM5CaNMXTZQ7xq4/yTfC3kPWtE4hFT34UJJflZBiLrxG4OsYxkHw/n5vKgmpspB3GfYuYTWhkDKiE8CYtyg87g=="}}' ); static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse()); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $this->getAuthenticatorAttestationResponseValidator($credentialRepository) + $this->getAuthenticatorAttestationResponseValidator() ->check($publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, 'webauthn.morselli.fr'); $publicKeyCredentialDescriptor = $publicKeyCredential->getPublicKeyCredentialDescriptor(['usb']); static::assertSame( diff --git a/tests/library/Functional/AttestationTest.php b/tests/library/Functional/AttestationTest.php index c1935b85..a1d04924 100644 --- a/tests/library/Functional/AttestationTest.php +++ b/tests/library/Functional/AttestationTest.php @@ -12,7 +12,6 @@ use Webauthn\Exception\InvalidDataException; use Webauthn\PublicKeyCredentialCreationOptions; use Webauthn\PublicKeyCredentialDescriptor; -use Webauthn\Tests\MemoryPublicKeyCredentialSourceRepository; /** * @internal @@ -40,8 +39,7 @@ public function anAttestationSignedWithEcDSA521ShouldBeVerified(): void $publicKeyCredential = $this->getPublicKeyCredentialLoader() ->load($response); static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse()); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $this->getAuthenticatorAttestationResponseValidator($credentialRepository) + $this->getAuthenticatorAttestationResponseValidator() ->check( $publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, diff --git a/tests/library/Functional/ConformanceTest.php b/tests/library/Functional/ConformanceTest.php index 9eefd338..7ebcc05c 100644 --- a/tests/library/Functional/ConformanceTest.php +++ b/tests/library/Functional/ConformanceTest.php @@ -7,7 +7,6 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use Webauthn\PublicKeyCredentialCreationOptions; -use Webauthn\Tests\MemoryPublicKeyCredentialSourceRepository; /** * @internal @@ -26,9 +25,8 @@ public function validAttestationResponseWithLinkShouldSucceed(string $options, s $publicKeyCredentialCreationOptions = PublicKeyCredentialCreationOptions::createFromString($options); $publicKeyCredential = $this->getPublicKeyCredentialLoader() ->load($response); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); // When - $pkSource = $this->getAuthenticatorAttestationResponseValidator($credentialRepository) + $pkSource = $this->getAuthenticatorAttestationResponseValidator() ->check( $publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, diff --git a/tests/library/Functional/Fido2AttestationStatementTest.php b/tests/library/Functional/Fido2AttestationStatementTest.php index 25d4d5e7..537ba24c 100644 --- a/tests/library/Functional/Fido2AttestationStatementTest.php +++ b/tests/library/Functional/Fido2AttestationStatementTest.php @@ -11,7 +11,6 @@ use Webauthn\PublicKeyCredentialParameters; use Webauthn\PublicKeyCredentialRpEntity; use Webauthn\PublicKeyCredentialUserEntity; -use Webauthn\Tests\MemoryPublicKeyCredentialSourceRepository; /** * @internal @@ -35,8 +34,7 @@ public function aFidoU2FAttestationCanBeVerified(): void '{"id":"eHouz_Zi7-BmByHjJ_tx9h4a1WZsK4IzUmgGjkhyOodPGAyUqUp_B9yUkflXY3yHWsNtsrgCXQ3HjAIFUeZB-w","type":"public-key","rawId":"eHouz/Zi7+BmByHjJ/tx9h4a1WZsK4IzUmgGjkhyOodPGAyUqUp/B9yUkflXY3yHWsNtsrgCXQ3HjAIFUeZB+w==","response":{"clientDataJSON":"eyJjaGFsbGVuZ2UiOiJwR1JhQmZmOXpwYXczQ0RBc2dncE9NUm9uSmFxTVhZamt2SUdUUHQzckhILTUzUkNXN0xROWw0Tm1HY3Y4ZE5aU05MRHJ2UURLYVNOaEZqdmlnZ2NaQSIsImNsaWVudEV4dGVuc2lvbnMiOnt9LCJoYXNoQWxnb3JpdGhtIjoiU0hBLTI1NiIsIm9yaWdpbiI6Imh0dHBzOi8vbG9jYWxob3N0Ojg0NDMiLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0","attestationObject":"o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIhALAccRlhFqq41JTqOC3cHkkN+O6ouvv4izWZY2W7NFh/AiBndeDPR6P2DZzia1sD4JFa87f3t/8bUgWzOsELduLkRWN4NWOBWQLCMIICvjCCAaagAwIBAgIEdIb9wjANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbzELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTk1NTAwMzg0MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJVd8633JH0xde/9nMTzGk6HjrrhgQlWYVD7OIsuX2Unv1dAmqWBpQ0KxS8YRFwKE1SKE1PIpOWacE5SO8BN6+2jbDBqMCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS4xMBMGCysGAQQBguUcAgEBBAQDAgUgMCEGCysGAQQBguUcAQEEBBIEEPigEfOMCk0VgAYXER+e3H0wDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAMVxIgOaaUn44Zom9af0KqG9J655OhUVBVW+q0As6AIod3AH5bHb2aDYakeIyyBCnnGMHTJtuekbrHbXYXERIn4aKdkPSKlyGLsA/A+WEi+OAfXrNVfjhrh7iE6xzq0sg4/vVJoywe4eAJx0fS+Dl3axzTTpYl71Nc7p/NX6iCMmdik0pAuYJegBcTckE3AoYEg4K99AM/JaaKIblsbFh8+3LxnemeNf7UwOczaGGvjS6UzGVI0Odf9lKcPIwYhuTxM5CaNMXTZQ7xq4/yTfC3kPWtE4hFT34UJJflZBiLrxG4OsYxkHw/n5vKgmpspB3GfYuYTWhkDKiE8CYtyg87mhhdXRoRGF0YVjESZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2NBAAAAAAAAAAAAAAAAAAAAAAAAAAAAQHh6Ls/2Yu/gZgch4yf7cfYeGtVmbCuCM1JoBo5IcjqHTxgMlKlKfwfclJH5V2N8h1rDbbK4Al0Nx4wCBVHmQfulAQIDJiABIVgglXnq9GsW6ygN/2GbeIOaWVzHFfPMrI71au4rDiRbHvMiWCD+erreXwgwlwh0oMlxdGH2GjPQv6dXA/U7GKXf+g1Biw=="}}' ); static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse()); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $this->getAuthenticatorAttestationResponseValidator($credentialRepository) + $this->getAuthenticatorAttestationResponseValidator() ->check($publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, 'localhost'); } } diff --git a/tests/library/Functional/NoneAttestationStatementTest.php b/tests/library/Functional/NoneAttestationStatementTest.php index 33da8cd3..fa2b8186 100644 --- a/tests/library/Functional/NoneAttestationStatementTest.php +++ b/tests/library/Functional/NoneAttestationStatementTest.php @@ -11,7 +11,6 @@ use Webauthn\PublicKeyCredentialParameters; use Webauthn\PublicKeyCredentialRpEntity; use Webauthn\PublicKeyCredentialUserEntity; -use Webauthn\Tests\MemoryPublicKeyCredentialSourceRepository; /** * @internal @@ -35,8 +34,7 @@ public function aNoneAttestationCanBeVerified(): void '{"id":"mMihuIx9LukswxBOMjMHDf6EAONOy7qdWhaQQ7dOtViR2cVB_MNbZxURi2cvgSvKSILb3mISe9lPNG9sYgojuY5iNinYOg6hRVxmm0VssuNG2pm1-RIuTF9DUtEJZEEK","type":"public-key","rawId":"mMihuIx9LukswxBOMjMHDf6EAONOy7qdWhaQQ7dOtViR2cVB/MNbZxURi2cvgSvKSILb3mISe9lPNG9sYgojuY5iNinYOg6hRVxmm0VssuNG2pm1+RIuTF9DUtEJZEEK","response":{"clientDataJSON":"eyJjaGFsbGVuZ2UiOiI5V3FncFJJWXZHTUNVWWlGVDIwbzFVN2hTRDE5M2sxMXp1NHRLUDd3UmNyRTI2enMxemM0TEh5UGludlBHUzg2d3U2YkR2cHdidDhYcDJiUTNWQlJTUSIsImNsaWVudEV4dGVuc2lvbnMiOnt9LCJoYXNoQWxnb3JpdGhtIjoiU0hBLTI1NiIsIm9yaWdpbiI6Imh0dHBzOi8vbG9jYWxob3N0Ojg0NDMiLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0","attestationObject":"o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjkSZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2NBAAAAAAAAAAAAAAAAAAAAAAAAAAAAYJjIobiMfS7pLMMQTjIzBw3+hADjTsu6nVoWkEO3TrVYkdnFQfzDW2cVEYtnL4ErykiC295iEnvZTzRvbGIKI7mOYjYp2DoOoUVcZptFbLLjRtqZtfkSLkxfQ1LRCWRBCqUBAgMmIAEhWCAcPxwKyHADVjTgTsat4R/Jax6PWte50A8ZasMm4w6RxCJYILt0FCiGwC6rBrh3ySNy0yiUjZpNGAhW+aM9YYyYnUTJ"}}' ); static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse()); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $this->getAuthenticatorAttestationResponseValidator($credentialRepository) + $this->getAuthenticatorAttestationResponseValidator() ->check($publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, 'localhost'); } } diff --git a/tests/library/Functional/PackedAttestationStatementTest.php b/tests/library/Functional/PackedAttestationStatementTest.php index 660221b7..2f4bda26 100644 --- a/tests/library/Functional/PackedAttestationStatementTest.php +++ b/tests/library/Functional/PackedAttestationStatementTest.php @@ -15,7 +15,6 @@ use Webauthn\PublicKeyCredentialParameters; use Webauthn\PublicKeyCredentialRpEntity; use Webauthn\PublicKeyCredentialUserEntity; -use Webauthn\Tests\MemoryPublicKeyCredentialSourceRepository; /** * @internal @@ -39,8 +38,7 @@ public function aPackedAttestationCanBeVerified(): void '{"id":"xYw3gEj0LVL83JXz7oKL14XQjh9W1NMFrTALWI-lqXl7ndKW-n8JFYsBCuKbZA3zRAUxAZDHG_tXHsAi6TbO0Q","type":"public-key","rawId":"xYw3gEj0LVL83JXz7oKL14XQjh9W1NMFrTALWI+lqXl7ndKW+n8JFYsBCuKbZA3zRAUxAZDHG/tXHsAi6TbO0Q==","response":{"clientDataJSON":"eyJjaGFsbGVuZ2UiOiIzMnVyUkIxTERmeWZZZVU5bXlDUGZyaHJ2Tm9WSTI3X18tUFdXWVZ4QUlTcEltM0dxZ1gtak51ZFBndk9aeTk2VVBOdkVrQ1dDQXJXMGp0cFFaRkdBZyIsIm9yaWdpbiI6Imh0dHBzOi8vbG9jYWxob3N0Ojg0NDMiLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0","attestationObject":"o2NmbXRmcGFja2VkZ2F0dFN0bXSjY2FsZyZjc2lnWEgwRgIhAOkogofSKvV0ma9Ejb3WH44tmXrUhSNK5qg7blgjR1n8AiEAuMsQaAsw27slMfM+wLfe4ozk+Mv8Rxdluhj59hLP4fxjeDVjgVkCwjCCAr4wggGmoAMCAQICBHSG/cIwDQYJKoZIhvcNAQELBQAwLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290IENBIFNlcmlhbCA0NTcyMDA2MzEwIBcNMTQwODAxMDAwMDAwWhgPMjA1MDA5MDQwMDAwMDBaMG8xCzAJBgNVBAYTAlNFMRIwEAYDVQQKDAlZdWJpY28gQUIxIjAgBgNVBAsMGUF1dGhlbnRpY2F0b3IgQXR0ZXN0YXRpb24xKDAmBgNVBAMMH1l1YmljbyBVMkYgRUUgU2VyaWFsIDE5NTUwMDM4NDIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASVXfOt9yR9MXXv/ZzE8xpOh4664YEJVmFQ+ziLLl9lJ79XQJqlgaUNCsUvGERcChNUihNTyKTlmnBOUjvATevto2wwajAiBgkrBgEEAYLECgIEFTEuMy42LjEuNC4xLjQxNDgyLjEuMTATBgsrBgEEAYLlHAIBAQQEAwIFIDAhBgsrBgEEAYLlHAEBBAQSBBD4oBHzjApNFYAGFxEfntx9MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBADFcSIDmmlJ+OGaJvWn9CqhvSeueToVFQVVvqtALOgCKHdwB+Wx29mg2GpHiMsgQp5xjB0ybbnpG6x212FxESJ+GinZD0ipchi7APwPlhIvjgH16zVX44a4e4hOsc6tLIOP71SaMsHuHgCcdH0vg5d2sc006WJe9TXO6fzV+ogjJnYpNKQLmCXoAXE3JBNwKGBIOCvfQDPyWmiiG5bGxYfPty8Z3pnjX+1MDnM2hhr40ulMxlSNDnX/ZSnDyMGIbk8TOQmjTF02UO8auP8k3wt5D1rROIRU9+FCSX5WQYi68RuDrGMZB8P5+byoJqbKQdxn2LmE1oZAyohPAmLcoPO5oYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAHz4oBHzjApNFYAGFxEfntx9AEDFjDeASPQtUvzclfPugovXhdCOH1bU0wWtMAtYj6WpeXud0pb6fwkViwEK4ptkDfNEBTEBkMcb+1cewCLpNs7RpQECAyYgASFYIBECPLnZwCFJ/2Pam0zUQOi4QQAwCKdAZ++36lPi7yvbIlgg4+9scyMxQeQjYGIgli1h5Sh2mlv8BwXwwQKUvbtS+KY="}}' ); static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse()); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $this->getAuthenticatorAttestationResponseValidator($credentialRepository) + $this->getAuthenticatorAttestationResponseValidator() ->check($publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, 'localhost'); $publicKeyCredentialDescriptor = $publicKeyCredential->getPublicKeyCredentialDescriptor(['usb']); static::assertSame( @@ -94,8 +92,7 @@ public function aPackedAttestationWithSelfStatementCanBeVerified(): void '{"id":"AFkzwaxVuCUz4qFPaNAgnYgoZKKTtvGIAaIASAbnlHGy8UktdI_jN0CetpIkiw9--R0AF9a6OJnHD-G4aIWur-Pxj-sI9xDE-AVeQKve","type":"public-key","rawId":"AFkzwaxVuCUz4qFPaNAgnYgoZKKTtvGIAaIASAbnlHGy8UktdI/jN0CetpIkiw9++R0AF9a6OJnHD+G4aIWur+Pxj+sI9xDE+AVeQKve","response":{"clientDataJSON":"eyJjaGFsbGVuZ2UiOiJvRlVHaFVldlFIWDdKNm80T0ZhdTVQYm5jQ0FUYUh3akhETEx6Q1RwaXl3Iiwib3JpZ2luIjoiaHR0cHM6Ly9zcG9ta3ktd2ViYXV0aG4uaGVyb2t1YXBwLmNvbSIsInR5cGUiOiJ3ZWJhdXRobi5jcmVhdGUifQ","attestationObject":"o2NmbXRmcGFja2VkZ2F0dFN0bXSiY2FsZyZjc2lnWEcwRQIgAMCQZYRl2cA+ab2MB3OGBCbq3j62rSubwhaCVSHJvKMCIQD0mMLs/5jjwd0KxYzb9/iM15T1gJ3L1Uv5BnMtQtVYBmhhdXRoRGF0YVjStIXbbgSILsWHHbR0Fjkl96X4ROZYLvVtOopBWCQoAqpFXE8bBwAAAAAAAAAAAAAAAAAAAAAATgBZM8GsVbglM+KhT2jQIJ2IKGSik7bxiAGiAEgG55RxsvFJLXSP4zdAnraSJIsPfvkdABfWujiZxw/huGiFrq/j8Y/rCPcQxPgFXkCr3qUBAgMmIAEhWCBOSwRVQxXPb76nvmQ2HQ8i5Bin8M4zfZCqIlKXrcxxmyJYIOFCAZ9+rRhklvn1nk2TahaCvpH96emEuKoGxpEObvQg"}}' ); static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse()); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $this->getAuthenticatorAttestationResponseValidator($credentialRepository) + $this->getAuthenticatorAttestationResponseValidator() ->check( $publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, @@ -150,8 +147,7 @@ public function p2(): void '{"id":"RSRHHrZblfX23SKbu09qBzVp8Y1W1c9GI1EtHZ9gDzY","rawId":"RSRHHrZblfX23SKbu09qBzVp8Y1W1c9GI1EtHZ9gDzY","response":{"attestationObject":"o2NmbXRmcGFja2VkZ2F0dFN0bXSjY2FsZyZjc2lnWEYwRAIgPjEY0D6cbc2ByBEvr1cu2QQvPewY7xdk-3E7XxpvW3YCIDswTHA5eoieLK0dJlHsneEJ0nmMCbyOP5Qt2m4s5B9-Y3g1Y4JZApIwggKOMIICNKADAgECAgEBMAoGCCqGSM49BAMCMIGvMSYwJAYDVQQDDB1GSURPMiBJTlRFUk1FRElBVEUgcHJpbWUyNTZ2MTExMC8GCSqGSIb3DQEJARYiY29uZm9ybWFuY2UtdG9vbHNAZmlkb2FsbGlhbmNlLm9yZzEWMBQGA1UECgwNRklETyBBbGxpYW5jZTEMMAoGA1UECwwDQ1dHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCTVkxEjAQBgNVBAcMCVdha2VmaWVsZDAeFw0xODA1MjMxNDM3NDFaFw0yODA1MjAxNDM3NDFaMIHCMSMwIQYDVQQDDBpGSURPMiBCQVRDSCBLRVkgcHJpbWUyNTZ2MTExMC8GCSqGSIb3DQEJARYiY29uZm9ybWFuY2UtdG9vbHNAZmlkb2FsbGlhbmNlLm9yZzEWMBQGA1UECgwNRklETyBBbGxpYW5jZTEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1ZMRIwEAYDVQQHDAlXYWtlZmllbGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS62WKs8a1SL5r7CgySHBfb6zqZk9Cko2ZjvsT1y_Ia-4BkaWUcUZGD9HyRD8wqNGUytw_rxxbbHQ4BvVduKUhkoywwKjAJBgNVHRMEAjAAMB0GA1UdDgQWBBRKVOUG0pFET20PM13W_cdGbLlfVDAKBggqhkjOPQQDAgNIADBFAiEAuVs2tHN9o6wQ0w2-9euV5QQnQlpElX874Yah038n6kUCIE0LrMA4QKR8Kk_1-lvGmHHKnpym_RyhfAzWkYRzNyl4WQQ1MIIEMTCCAhmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBoTEYMBYGA1UEAwwPRklETzIgVEVTVCBST09UMTEwLwYJKoZIhvcNAQkBFiJjb25mb3JtYW5jZS10b29sc0BmaWRvYWxsaWFuY2Uub3JnMRYwFAYDVQQKDA1GSURPIEFsbGlhbmNlMQwwCgYDVQQLDANDV0cxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNWTESMBAGA1UEBwwJV2FrZWZpZWxkMB4XDTE4MDcyMzE0MjkwN1oXDTQ1MTIwODE0MjkwN1owga8xJjAkBgNVBAMMHUZJRE8yIElOVEVSTUVESUFURSBwcmltZTI1NnYxMTEwLwYJKoZIhvcNAQkBFiJjb25mb3JtYW5jZS10b29sc0BmaWRvYWxsaWFuY2Uub3JnMRYwFAYDVQQKDA1GSURPIEFsbGlhbmNlMQwwCgYDVQQLDANDV0cxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNWTESMBAGA1UEBwwJV2FrZWZpZWxkMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3EEd31Vtf01zjKl1FHpVcfRjACkj1m-0e16XhyBwWQUOyc6HqW80V4rU3Qi0wnzV6SxNRuiUXLLT5l_bS0l586MvMC0wDAYDVR0TBAUwAwEB_zAdBgNVHQ4EFgQUZ8EZkpBb9V0AwdYhDowtdiGSR8AwDQYJKoZIhvcNAQELBQADggIBAAuYLqezVLsHJ3Yn7-XcJWehiEj0xHIkHTMZjaPZxPQUQDtm7UNA3SXYnwPBp0EHdvXSIJPFOPFrnGOKs7r0WWius-gCK1NmwFJSayp5U2b43YjN6Ik2PVk4gfXsn5iv2YBL-1vQxBVu764d9vqY0jRdVcsbjBKZ2tV-rMqrTQ1RvsNGC43ZF4tHIrkSctEPQPdL5jCoAMYJ0XwqJeWkFJR6WTE4ivvDgqfLEqKtOUDd_Yst-LuAHihlFnrio2BMDbICoJ_r9fgNXW1MNnFmIOdzouZvw0C5bflrNYaJLsF8QnpGgb4ngfZ7td32F7-0pIMLljzcMhT5UJFqSD4G_XmTBN5J1IidhAEtVBO5K2ljYN3EDtr-rWNuPufhZhMrlopxgoax7ME9LGLZoUBpVmtGwlfXxCy-vWwjuuEYlqHpy7Il9eYZpgu_mWxfQ9VR49QR0fXoqAGVFaJxIgyUmR7VcV5ZlN40AYaxD87ReUZ-u9Hc6vxOByz3826ylvi9hdovlhFhe3LYnDVQQS11B7BQLxmDKr-wxNMwxmmey_o1yI0gohNiI4sQoTGMP2hWMJsdDesrl3iQ2LvHwklzikz0emUbCwkN_LVxUkEcp9U-RYL8XbO0NrMYLVVwjcvBTKKH9u4IzLuYuKQLdpXVxDsdcyNj_jb-hhcWNlPwbVyDaGF1dGhEYXRhWKSWBOqCgk6YpK2hS0Ri0Nc6jsRpEw2pGxkwdFkin3SjWUEAAABpgPU9HoUuQ-27P9AvEyLlrwAgRSRHHrZblfX23SKbu09qBzVp8Y1W1c9GI1EtHZ9gDzalAQIDJiABIVggMVh-zNGe5B0_5d0YHZ78BUJtmLr5pLuXmWef-O7ONZEiWCCf6mnMspgsRLzt3_HP0hW3WmlE1m-FkUqGr9nXQz5B3g","clientDataJSON":"eyJvcmlnaW4iOiJodHRwczovL3dlYmF1dGhuLnNwb21reS1sYWJzLmNvbSIsImNoYWxsZW5nZSI6IktoV1ExMkdsdHA5MlJNb2RvVFBnRHFwZ1hDdlI3M0pYS296aWpISWZ3SEUiLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0"},"type":"public-key"}' ); static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse()); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $this->getAuthenticatorAttestationResponseValidator($credentialRepository) + $this->getAuthenticatorAttestationResponseValidator() ->check( $publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, diff --git a/tests/library/Functional/SubDomainRelyingPartyTest.php b/tests/library/Functional/SubDomainRelyingPartyTest.php index ef1f42dc..372a3436 100644 --- a/tests/library/Functional/SubDomainRelyingPartyTest.php +++ b/tests/library/Functional/SubDomainRelyingPartyTest.php @@ -7,7 +7,6 @@ use PHPUnit\Framework\Attributes\Test; use Webauthn\AuthenticatorAttestationResponse; use Webauthn\PublicKeyCredentialCreationOptions; -use Webauthn\Tests\MemoryPublicKeyCredentialSourceRepository; /** * @internal @@ -25,8 +24,7 @@ public function anAuthenticatorAttestationResponseWithSubdomainCanBeVerified(): '{"id":"-cGSjQwC4UBTsh2Mw6guep2uTdLXOExla3QJrVpByOkEWJaOljo54PWOazmHtxBuV5DeysX7qjohoGYK2YibdA","type":"public-key","rawId":"+cGSjQwC4UBTsh2Mw6guep2uTdLXOExla3QJrVpByOkEWJaOljo54PWOazmHtxBuV5DeysX7qjohoGYK2YibdA==","response":{"clientDataJSON":"eyJjaGFsbGVuZ2UiOiJ4R1EyaDJiSzJ0Ym45NmVOdXRib0c1M0Z2VVQzMElWXzJUaG9lS1B1Nzc4Iiwib3JpZ2luIjoiaHR0cHM6Ly93ZWJhdXRobi5zcG9ta3ktbGFicy5jb20iLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0","attestationObject":"o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIhALotmA9bjE8DC5afT4C6QJHwB2TDCgh+/DSpIuxt1Z2dAiBzVRmktx9Ur1sjxZJvjhAnzZCRDicD/h2dyd8a+MkVGWN4NWOBWQLCMIICvjCCAaagAwIBAgIEdIb9wjANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbzELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTk1NTAwMzg0MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJVd8633JH0xde/9nMTzGk6HjrrhgQlWYVD7OIsuX2Unv1dAmqWBpQ0KxS8YRFwKE1SKE1PIpOWacE5SO8BN6+2jbDBqMCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS4xMBMGCysGAQQBguUcAgEBBAQDAgUgMCEGCysGAQQBguUcAQEEBBIEEPigEfOMCk0VgAYXER+e3H0wDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAMVxIgOaaUn44Zom9af0KqG9J655OhUVBVW+q0As6AIod3AH5bHb2aDYakeIyyBCnnGMHTJtuekbrHbXYXERIn4aKdkPSKlyGLsA/A+WEi+OAfXrNVfjhrh7iE6xzq0sg4/vVJoywe4eAJx0fS+Dl3axzTTpYl71Nc7p/NX6iCMmdik0pAuYJegBcTckE3AoYEg4K99AM/JaaKIblsbFh8+3LxnemeNf7UwOczaGGvjS6UzGVI0Odf9lKcPIwYhuTxM5CaNMXTZQ7xq4/yTfC3kPWtE4hFT34UJJflZBiLrxG4OsYxkHw/n5vKgmpspB3GfYuYTWhkDKiE8CYtyg87mhhdXRoRGF0YVjEzJVnqxWDxWv1dKGpGXUmkUO/MGMFSRae4FA9zhbiR3VBAAAAAAAAAAAAAAAAAAAAAAAAAAAAQPnBko0MAuFAU7IdjMOoLnqdrk3S1zhMZWt0Ca1aQcjpBFiWjpY6OeD1jms5h7cQbleQ3srF+6o6IaBmCtmIm3SlAQIDJiABIVggZ9kAaP2QIzTF401zK9+GnJ9t5P5nZMd+7Uq2dj9zrDciWCAYPJnCkmc15U8txqQB+CdSKUhpVrhITkmBPycz6nzp8g=="}}' ); static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse()); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $this->getAuthenticatorAttestationResponseValidator($credentialRepository) + $this->getAuthenticatorAttestationResponseValidator() ->check($publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, 'localhost'); } } diff --git a/tests/library/Functional/W10Test.php b/tests/library/Functional/W10Test.php index b056fc18..b09226d9 100644 --- a/tests/library/Functional/W10Test.php +++ b/tests/library/Functional/W10Test.php @@ -15,7 +15,6 @@ use Webauthn\PublicKeyCredentialCreationOptions; use Webauthn\PublicKeyCredentialDescriptor; use Webauthn\PublicKeyCredentialRequestOptions; -use Webauthn\Tests\MemoryPublicKeyCredentialSourceRepository; use Webauthn\TrustPath\EmptyTrustPath; /** @@ -39,8 +38,7 @@ public function anAttestationCanBeVerified( $publicKeyCredential = $this->getPublicKeyCredentialLoader() ->load($publicKeyCredentialData); static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse()); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $publicKeyCredentialSource = $this->getAuthenticatorAttestationResponseValidator($credentialRepository) + $publicKeyCredentialSource = $this->getAuthenticatorAttestationResponseValidator() ->check($publicKeyCredential->getResponse(), $publicKeyCredentialCreationOptions, $host); $publicKeyCredentialDescriptor = $publicKeyCredential->getPublicKeyCredentialDescriptor(['usb']); static::assertSame($credentialId, Base64UrlSafe::decode($publicKeyCredential->getId())); @@ -127,11 +125,9 @@ public function anAssertionCanBeVerified(): void true ) ); - $credentialRepository = new MemoryPublicKeyCredentialSourceRepository(); - $credentialRepository->saveCredentialSource($publicKeyCredentialSource); - $this->getAuthenticatorAssertionResponseValidator($credentialRepository) + $publicKeyCredentialSource = $this->getAuthenticatorAssertionResponseValidator() ->check( - $publicKeyCredential->getRawId(), + $publicKeyCredentialSource, $publicKeyCredential->getResponse(), $publicKeyCredentialRequestOptions, 'webauthn.spomky-labs.com', diff --git a/tests/library/Unit/AttestationStatement/TPMAttestationStatementSupportTest.php b/tests/library/Unit/AttestationStatement/TPMAttestationStatementSupportTest.php index fa38c9e6..f87a5238 100644 --- a/tests/library/Unit/AttestationStatement/TPMAttestationStatementSupportTest.php +++ b/tests/library/Unit/AttestationStatement/TPMAttestationStatementSupportTest.php @@ -23,7 +23,6 @@ use Webauthn\PublicKeyCredentialRpEntity; use Webauthn\PublicKeyCredentialUserEntity; use Webauthn\Tests\Unit\DummyMetadataStatementRepository; -use Webauthn\Tests\Unit\DummyPublicKeyCredentialSourceRepository; /** * @internal @@ -35,7 +34,6 @@ public function theAttestationStatementIsAValidECC(): void { //Given $metadataStatementRepository = new DummyMetadataStatementRepository(); - $pkSourceRepository = new DummyPublicKeyCredentialSourceRepository(); $attnManager = AttestationStatementSupportManager::create(); $attnManager->add(TPMAttestationStatementSupport::create(SystemClock::fromSystemTimezone())); $attnManager->add(NoneAttestationStatementSupport::create()); @@ -50,7 +48,7 @@ public function theAttestationStatementIsAValidECC(): void )->setAttestation(PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT); $validator = AuthenticatorAttestationResponseValidator::create( $attnManager, - $pkSourceRepository, + null, null, ExtensionOutputCheckerHandler::create(), )->enableMetadataStatementSupport( diff --git a/tests/library/Unit/DummyPublicKeyCredentialSourceRepository.php b/tests/library/Unit/DummyPublicKeyCredentialSourceRepository.php deleted file mode 100644 index 196bd60d..00000000 --- a/tests/library/Unit/DummyPublicKeyCredentialSourceRepository.php +++ /dev/null @@ -1,29 +0,0 @@ -getContainer()->get(PublicKeyCredentialLoader::class)->load( + $publicKeyCredential = self::getContainer()->get(PublicKeyCredentialLoader::class)->load( '{"id":"eHouz_Zi7-BmByHjJ_tx9h4a1WZsK4IzUmgGjkhyOodPGAyUqUp_B9yUkflXY3yHWsNtsrgCXQ3HjAIFUeZB-w","type":"public-key","rawId":"eHouz/Zi7+BmByHjJ/tx9h4a1WZsK4IzUmgGjkhyOodPGAyUqUp/B9yUkflXY3yHWsNtsrgCXQ3HjAIFUeZB+w==","response":{"authenticatorData":"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAAew","clientDataJSON":"eyJjaGFsbGVuZ2UiOiJHMEpiTExuZGVmM2EwSXkzUzJzU1FBOHVPNFNPX3plNkZaTUF1UEk2LXhJIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6ODQ0MyIsInR5cGUiOiJ3ZWJhdXRobi5nZXQifQ","signature":"MEUCIEY/vcNkbo/LdMTfLa24ZYLlMMVMRd8zXguHBvqud9AJAiEAwCwpZpvcMaqCrwv85w/8RGiZzE+gOM61ffxmgEDeyhM=","userHandle":null}}' ); + $publicKeyCredentialSource = self::getContainer()->get( + PublicKeyCredentialSourceRepositoryInterface::class + )->findOneByCredentialId($publicKeyCredential->getRawId()); $descriptor = $publicKeyCredential->getPublicKeyCredentialDescriptor(); static::assertSame(PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY, $descriptor->getType()); static::assertSame( @@ -61,8 +65,8 @@ public function anAssertionResponseCanBeLoadedAndVerified(): void $response = $publicKeyCredential->getResponse(); static::assertInstanceOf(AuthenticatorAssertionResponse::class, $response); static::assertNull($response->getUserHandle()); - self::$kernel->getContainer()->get(AuthenticatorAssertionResponseValidator::class)->check( - $publicKeyCredential->getRawId(), + self::getContainer()->get(AuthenticatorAssertionResponseValidator::class)->check( + $publicKeyCredentialSource, $publicKeyCredential->getResponse(), $publicKeyCredentialRequestOptions, 'localhost', @@ -83,7 +87,7 @@ public function aPublicKeyCredentialCreationOptionsCanBeCreatedFromProfile(): vo ), ]; /** @var PublicKeyCredentialRequestOptionsFactory $factory */ - $factory = self::$kernel->getContainer()->get(PublicKeyCredentialRequestOptionsFactory::class); + $factory = self::getContainer()->get(PublicKeyCredentialRequestOptionsFactory::class); $options = $factory->create('default', $allowedCredentials); static::assertNull($options->getTimeout()); static::assertSame('localhost', $options->getRpId()); diff --git a/tests/symfony/functional/FailureHandler.php b/tests/symfony/functional/FailureHandler.php index 5160c5da..73207860 100644 --- a/tests/symfony/functional/FailureHandler.php +++ b/tests/symfony/functional/FailureHandler.php @@ -24,9 +24,8 @@ public function onFailure(Request $request, Throwable $exception = null): Respon $data = [ 'status' => 'error', 'errorMessage' => $exception->getMessage(), - 'errorCode' => $exception->getCode(), ]; - return new JsonResponse($data, Response::HTTP_UNAUTHORIZED); + return new JsonResponse($data, $exception->getCode() ?: Response::HTTP_UNAUTHORIZED); } } diff --git a/tests/symfony/functional/Firewall/SecuredAreaTest.php b/tests/symfony/functional/Firewall/SecuredAreaTest.php index fd040baf..c5a7d073 100644 --- a/tests/symfony/functional/Firewall/SecuredAreaTest.php +++ b/tests/symfony/functional/Firewall/SecuredAreaTest.php @@ -78,7 +78,7 @@ public function aUserCannotBeBeAuthenticatedInAbsenceOfOptions(): void self::assertResponseStatusCodeSame(Response::HTTP_UNAUTHORIZED); static::assertSame( - '{"status":"error","errorMessage":"No public key credential options available for this session.","errorCode":0}', + '{"status":"error","errorMessage":"No public key credential options available for this session."}', $this->client->getResponse() ->getContent() ); diff --git a/tests/symfony/functional/PublicKeyCredentialSourceRepository.php b/tests/symfony/functional/PublicKeyCredentialSourceRepository.php index f891fc3f..5efd13cd 100644 --- a/tests/symfony/functional/PublicKeyCredentialSourceRepository.php +++ b/tests/symfony/functional/PublicKeyCredentialSourceRepository.php @@ -8,13 +8,14 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Uid\Uuid; use Webauthn\AttestationStatement\AttestationStatement; +use Webauthn\Bundle\Repository\CanSaveCredentialSource; +use Webauthn\Bundle\Repository\PublicKeyCredentialSourceRepositoryInterface; use Webauthn\PublicKeyCredentialDescriptor; use Webauthn\PublicKeyCredentialSource; -use Webauthn\PublicKeyCredentialSourceRepository as PublicKeyCredentialSourceRepositoryInterface; use Webauthn\PublicKeyCredentialUserEntity; use Webauthn\TrustPath\EmptyTrustPath; -final class PublicKeyCredentialSourceRepository implements PublicKeyCredentialSourceRepositoryInterface +final class PublicKeyCredentialSourceRepository implements PublicKeyCredentialSourceRepositoryInterface, CanSaveCredentialSource { public function __construct( private readonly CacheItemPoolInterface $cacheItemPool