Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 181 additions & 1 deletion .ci-tools/phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,30 @@ parameters:
count: 1
path: ../src/symfony/src/DependencyInjection/Compiler/LoggerSetterCompilerPass.php

-
rawMessage: 'Method Webauthn\Bundle\DependencyInjection\Compiler\PasskeyEndpointsCompilerPass::createControllerDefinition() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.'
identifier: ergebnis.noParameterWithContainerTypeDeclaration
count: 1
path: ../src/symfony/src/DependencyInjection/Compiler/PasskeyEndpointsCompilerPass.php

-
rawMessage: 'Method Webauthn\Bundle\DependencyInjection\Compiler\PasskeyEndpointsCompilerPass::createPasskeyEndpointsResponse() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.'
identifier: ergebnis.noParameterWithContainerTypeDeclaration
count: 1
path: ../src/symfony/src/DependencyInjection/Compiler/PasskeyEndpointsCompilerPass.php

-
rawMessage: 'Method Webauthn\Bundle\DependencyInjection\Compiler\PasskeyEndpointsCompilerPass::process() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.'
identifier: ergebnis.noParameterWithContainerTypeDeclaration
count: 1
path: ../src/symfony/src/DependencyInjection/Compiler/PasskeyEndpointsCompilerPass.php

-
rawMessage: 'Parameter #1 $value of method Webauthn\Bundle\DependencyInjection\Compiler\PasskeyEndpointsCompilerPass::createUrlDefinition() expects array<string, mixed>|string, array|bool|float|int|string given.'
identifier: argument.type
count: 3
path: ../src/symfony/src/DependencyInjection/Compiler/PasskeyEndpointsCompilerPass.php

-
rawMessage: Anonymous function should return array but returns mixed.
identifier: return.type
Expand Down Expand Up @@ -831,6 +855,12 @@ parameters:
count: 1
path: ../src/symfony/src/DependencyInjection/WebauthnExtension.php

-
rawMessage: 'Method Webauthn\Bundle\DependencyInjection\WebauthnExtension::loadPasskeyEndpointsConfig() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.'
identifier: ergebnis.noParameterWithContainerTypeDeclaration
count: 1
path: ../src/symfony/src/DependencyInjection/WebauthnExtension.php

-
rawMessage: 'Method Webauthn\Bundle\DependencyInjection\WebauthnExtension::loadRequestControllersSupport() has a parameter $container with a type declaration of Symfony\Component\DependencyInjection\ContainerBuilder, but containers should not be injected.'
identifier: ergebnis.noParameterWithContainerTypeDeclaration
Expand Down Expand Up @@ -867,6 +897,12 @@ parameters:
count: 1
path: ../src/symfony/src/DependencyInjection/WebauthnExtension.php

-
rawMessage: 'Parameter #2 $config of method Webauthn\Bundle\DependencyInjection\WebauthnExtension::loadPasskeyEndpointsConfig() expects array<mixed>, mixed given.'
identifier: argument.type
count: 1
path: ../src/symfony/src/DependencyInjection/WebauthnExtension.php

-
rawMessage: 'Parameter #2 $config of method Webauthn\Bundle\DependencyInjection\WebauthnExtension::loadRequestControllersSupport() expects array<mixed>, mixed given.'
identifier: argument.type
Expand All @@ -882,7 +918,7 @@ parameters:
-
rawMessage: 'Parameter #2 $value of method Symfony\Component\DependencyInjection\Container::setParameter() expects array|bool|float|int|string|UnitEnum|null, mixed given.'
identifier: argument.type
count: 5
count: 9
path: ../src/symfony/src/DependencyInjection/WebauthnExtension.php

-
Expand Down Expand Up @@ -5049,6 +5085,54 @@ parameters:
count: 1
path: ../src/webauthn/src/Denormalizer/TrustPathDenormalizer.php

-
rawMessage: Constructor in Webauthn\Denormalizer\UrlNormalizer has parameter $urlGenerator with default value.
identifier: ergebnis.noConstructorParameterWithDefaultValue
count: 1
path: ../src/webauthn/src/Denormalizer/UrlNormalizer.php

-
rawMessage: 'Method Webauthn\Denormalizer\UrlNormalizer::__construct() has parameter $urlGenerator with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
count: 1
path: ../src/webauthn/src/Denormalizer/UrlNormalizer.php

-
rawMessage: 'Method Webauthn\Denormalizer\UrlNormalizer::__construct() has parameter $urlGenerator with null as default value.'
identifier: ergebnis.noParameterWithNullDefaultValue
count: 1
path: ../src/webauthn/src/Denormalizer/UrlNormalizer.php

-
rawMessage: 'Method Webauthn\Denormalizer\UrlNormalizer::getSupportedTypes() has parameter $format with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
count: 1
path: ../src/webauthn/src/Denormalizer/UrlNormalizer.php

-
rawMessage: 'Method Webauthn\Denormalizer\UrlNormalizer::normalize() has parameter $format with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
count: 1
path: ../src/webauthn/src/Denormalizer/UrlNormalizer.php

-
rawMessage: 'Method Webauthn\Denormalizer\UrlNormalizer::normalize() has parameter $format with null as default value.'
identifier: ergebnis.noParameterWithNullDefaultValue
count: 1
path: ../src/webauthn/src/Denormalizer/UrlNormalizer.php

-
rawMessage: 'Method Webauthn\Denormalizer\UrlNormalizer::supportsNormalization() has parameter $format with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
count: 1
path: ../src/webauthn/src/Denormalizer/UrlNormalizer.php

-
rawMessage: 'Method Webauthn\Denormalizer\UrlNormalizer::supportsNormalization() has parameter $format with null as default value.'
identifier: ergebnis.noParameterWithNullDefaultValue
count: 1
path: ../src/webauthn/src/Denormalizer/UrlNormalizer.php

-
rawMessage: 'Method Webauthn\Denormalizer\VerificationMethodANDCombinationsDenormalizer::getSupportedTypes() has parameter $format with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
Expand Down Expand Up @@ -7269,6 +7353,96 @@ parameters:
count: 1
path: ../src/webauthn/src/MetadataService/Statement/Version.php

-
rawMessage: Constructor in Webauthn\PasskeyEndpointsResponse has parameter $enroll with default value.
identifier: ergebnis.noConstructorParameterWithDefaultValue
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: Constructor in Webauthn\PasskeyEndpointsResponse has parameter $manage with default value.
identifier: ergebnis.noConstructorParameterWithDefaultValue
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: Constructor in Webauthn\PasskeyEndpointsResponse has parameter $prfUsageDetails with default value.
identifier: ergebnis.noConstructorParameterWithDefaultValue
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::__construct() has parameter $enroll with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::__construct() has parameter $enroll with null as default value.'
identifier: ergebnis.noParameterWithNullDefaultValue
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::__construct() has parameter $manage with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::__construct() has parameter $manage with null as default value.'
identifier: ergebnis.noParameterWithNullDefaultValue
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::__construct() has parameter $prfUsageDetails with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::__construct() has parameter $prfUsageDetails with null as default value.'
identifier: ergebnis.noParameterWithNullDefaultValue
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::create() has parameter $enroll with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::create() has parameter $enroll with null as default value.'
identifier: ergebnis.noParameterWithNullDefaultValue
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::create() has parameter $manage with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::create() has parameter $manage with null as default value.'
identifier: ergebnis.noParameterWithNullDefaultValue
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::create() has parameter $prfUsageDetails with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: 'Method Webauthn\PasskeyEndpointsResponse::create() has parameter $prfUsageDetails with null as default value.'
identifier: ergebnis.noParameterWithNullDefaultValue
count: 1
path: ../src/webauthn/src/PasskeyEndpointsResponse.php

-
rawMessage: Class "Webauthn\PublicKeyCredential" is not allowed to extend "Webauthn\Credential".
identifier: ergebnis.noExtends
Expand Down Expand Up @@ -7968,6 +8142,12 @@ parameters:
count: 1
path: ../src/webauthn/src/SimpleFakeCredentialGenerator.php

-
rawMessage: Constructor in Webauthn\Url has parameter $params with default value.
identifier: ergebnis.noConstructorParameterWithDefaultValue
count: 1
path: ../src/webauthn/src/Url.php

-
rawMessage: 'Method Webauthn\Util\Base64::decode() is not final, but since the containing class is abstract, it should be.'
identifier: ergebnis.finalInAbstractClass
Expand Down
33 changes: 33 additions & 0 deletions src/symfony/src/Controller/PasskeyEndpointsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Webauthn\Bundle\Controller;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
use Symfony\Component\Serializer\SerializerInterface;
use Webauthn\PasskeyEndpointsResponse;

/**
* Controller exposing the .well-known/passkey-endpoints endpoint.
*
* @see https://w3c.github.io/webappsec-passkey-endpoints/
*/
final readonly class PasskeyEndpointsController
{
public function __construct(
private PasskeyEndpointsResponse $passkeyEndpoints,
private SerializerInterface $serializer
) {
}

public function __invoke(): JsonResponse
{
$endpoints = $this->serializer->serialize($this->passkeyEndpoints, 'json', [
AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => true,
]);

return new JsonResponse($endpoints, 200, [], true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

declare(strict_types=1);

namespace Webauthn\Bundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Serializer\SerializerInterface;
use Webauthn\Bundle\Controller\PasskeyEndpointsController;
use Webauthn\Bundle\Routing\Loader;
use Webauthn\PasskeyEndpointsResponse;
use Webauthn\Url;

/**
* Compiler pass to register the .well-known/passkey-endpoints controller and route.
*
* @see https://w3c.github.io/webappsec-passkey-endpoints/
*/
final class PasskeyEndpointsCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
if (! $container->hasParameter('webauthn.passkey_endpoints.enabled')) {
return;
}

$enabled = $container->getParameter('webauthn.passkey_endpoints.enabled');
if ($enabled !== true) {
return;
}

$this->createPasskeyEndpointsResponse($container);
$this->createControllerDefinition($container);
}

private function createPasskeyEndpointsResponse(ContainerBuilder $container): void
{
$enroll = $container->getParameter('webauthn.passkey_endpoints.enroll');
$manage = $container->getParameter('webauthn.passkey_endpoints.manage');
$prfUsageDetails = $container->getParameter('webauthn.passkey_endpoints.prf_usage_details');

// Create Url definitions from string configuration
$enrollUrl = $enroll !== null ? $this->createUrlDefinition($enroll) : null;
$manageUrl = $manage !== null ? $this->createUrlDefinition($manage) : null;
$prfUrl = $prfUsageDetails !== null ? $this->createUrlDefinition($prfUsageDetails) : null;

$responseDefinition = new Definition(PasskeyEndpointsResponse::class, [$enrollUrl, $manageUrl, $prfUrl]);

$container->setDefinition(PasskeyEndpointsResponse::class, $responseDefinition);
}

/**
* Creates a Url definition from configuration value (string or array) using the serializer to denormalize it.
*
* @param string|array<string, mixed> $value
*/
private function createUrlDefinition(string|array $value): Definition
{
$urlDefinition = new Definition(Url::class);
$urlDefinition->setFactory([new Reference(SerializerInterface::class), 'denormalize']);
$urlDefinition->setArguments([$value, Url::class, 'json']);

return $urlDefinition;
}

private function createControllerDefinition(ContainerBuilder $container): void
{
if (! $container->hasDefinition(Loader::class)) {
return;
}

if (! $container->hasDefinition(PasskeyEndpointsResponse::class)) {
return;
}

$controllerDefinition = new Definition(
PasskeyEndpointsController::class,
[$container->getDefinition(PasskeyEndpointsResponse::class), new Reference(SerializerInterface::class)]
);
$controllerDefinition->setPublic(true);

$container->setDefinition(PasskeyEndpointsController::class, $controllerDefinition);

$loaderDefinition = $container->getDefinition(Loader::class);
$loaderDefinition->addMethodCall('add', [
'/.well-known/passkey-endpoints',
null,
PasskeyEndpointsController::class,
'GET',
]);
}
}
Loading
Loading