Skip to content

Commit 28f2c06

Browse files
committed
Add Signal interfaces and denormalizers for Webauthn serialization
Introduced `Signal` interfaces and their implementations (`AllAcceptedCredentials`, `CurrentUserDetails`, `UnknownCredential`) along with corresponding denormalizers. Updated the serializer factory and added test cases to ensure proper signal handling and serialization. Refactored constructors for cleaner code consistency.
1 parent f4cade2 commit 28f2c06

16 files changed

+305
-41
lines changed

src/webauthn/src/AttestationStatement/TPMAttestationStatementSupport.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,8 @@ final class TPMAttestationStatementSupport implements AttestationStatementSuppor
4141

4242
private readonly ClockInterface $clock;
4343

44-
public function __construct(
45-
null|ClockInterface $clock = null
46-
) {
44+
public function __construct(null|ClockInterface $clock = null)
45+
{
4746
$this->clock = $clock ?? new NativeClock();
4847
$this->dispatcher = new NullEventDispatcher();
4948
}

src/webauthn/src/CeremonyStep/CheckClientDataCollectorType.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@
1616
{
1717
private ClientDataCollectorManager $clientDataCollectorManager;
1818

19-
public function __construct(
20-
null|ClientDataCollectorManager $clientDataCollectorManager = null,
21-
) {
19+
public function __construct(null|ClientDataCollectorManager $clientDataCollectorManager = null)
20+
{
2221
$this->clientDataCollectorManager = $clientDataCollectorManager ?? new ClientDataCollectorManager([
2322
new WebauthnAuthenticationCollector(),
2423
]);

src/webauthn/src/CeremonyStep/CheckSignature.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@
2626
{
2727
private Manager $algorithmManager;
2828

29-
public function __construct(
30-
null|Manager $algorithmManager = null,
31-
) {
29+
public function __construct(null|Manager $algorithmManager = null)
30+
{
3231
$this->algorithmManager = $algorithmManager ?? Manager::create()->add(ES256::create(), RS256::create());
3332
}
3433

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Webauthn\Denormalizer;
6+
7+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
8+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
9+
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
10+
use Webauthn\PublicKeyCredentialDescriptor;
11+
use Webauthn\Signal\AllAcceptedCredentials;
12+
use function assert;
13+
14+
class SignalAllAcceptedCredentialsDenormalizer implements NormalizerInterface, NormalizerAwareInterface
15+
{
16+
use NormalizerAwareTrait;
17+
18+
/**
19+
* @return array<class-string, bool>
20+
*/
21+
public function getSupportedTypes(?string $format): array
22+
{
23+
return [
24+
AllAcceptedCredentials::class => true,
25+
];
26+
}
27+
28+
/**
29+
* @return array<string, mixed>
30+
*/
31+
public function normalize(mixed $data, ?string $format = null, array $context = []): array
32+
{
33+
assert($data instanceof AllAcceptedCredentials);
34+
35+
$normalized_rp = $this->normalizer->normalize($data->rp, $format, $context);
36+
37+
$normalized_user = $this->normalizer->normalize($data->user, $format, $context);
38+
39+
$normalized_credentials = array_map(function (PublicKeyCredentialDescriptor $credential) use (
40+
$format,
41+
$context
42+
) {
43+
return $this->normalizer->normalize($credential, $format, $context);
44+
}, $data->allAcceptedCredentials);
45+
46+
return [
47+
'rpId' => $normalized_rp['id'],
48+
'userId' => $normalized_user['id'],
49+
'allAcceptedCredentialIds' => array_map(
50+
fn (array $credential): string => $credential['id'],
51+
$normalized_credentials
52+
),
53+
];
54+
}
55+
56+
public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
57+
{
58+
return $data instanceof AllAcceptedCredentials;
59+
}
60+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Webauthn\Denormalizer;
6+
7+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
8+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
9+
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
10+
use Webauthn\Signal\CurrentUserDetails;
11+
use function assert;
12+
13+
class SignalCurrentUserDetailsDenormalizer implements NormalizerInterface, NormalizerAwareInterface
14+
{
15+
use NormalizerAwareTrait;
16+
17+
/**
18+
* @return array<class-string, bool>
19+
*/
20+
public function getSupportedTypes(?string $format): array
21+
{
22+
return [
23+
CurrentUserDetails::class => true,
24+
];
25+
}
26+
27+
/**
28+
* @return array<string, mixed>
29+
*/
30+
public function normalize(mixed $data, ?string $format = null, array $context = []): array
31+
{
32+
assert($data instanceof CurrentUserDetails);
33+
34+
$normalized_rp = $this->normalizer->normalize($data->rp, $format, $context);
35+
36+
$normalized_user = $this->normalizer->normalize($data->user, $format, $context);
37+
38+
return [
39+
'rpId' => $normalized_rp['id'],
40+
'userId' => $normalized_user['id'],
41+
'name' => $normalized_user['name'],
42+
'displayName' => $normalized_user['displayName'],
43+
];
44+
}
45+
46+
public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
47+
{
48+
return $data instanceof CurrentUserDetails;
49+
}
50+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Webauthn\Denormalizer;
6+
7+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
8+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
9+
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
10+
use Webauthn\Signal\UnknownCredential;
11+
use function assert;
12+
13+
class SignalUnknownCredentialDenormalizer implements NormalizerInterface, NormalizerAwareInterface
14+
{
15+
use NormalizerAwareTrait;
16+
17+
/**
18+
* @return array<class-string, bool>
19+
*/
20+
public function getSupportedTypes(?string $format): array
21+
{
22+
return [
23+
UnknownCredential::class => true,
24+
];
25+
}
26+
27+
/**
28+
* @return array<string, mixed>
29+
*/
30+
public function normalize(mixed $data, ?string $format = null, array $context = []): array
31+
{
32+
assert($data instanceof UnknownCredential);
33+
34+
$normalized_rp = $this->normalizer->normalize($data->rp, $format, $context);
35+
36+
$normalized_credential = $this->normalizer->normalize($data->credential, $format, $context);
37+
38+
return [
39+
'rpId' => $normalized_rp['id'],
40+
'credentialId' => $normalized_credential['id'],
41+
];
42+
}
43+
44+
public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
45+
{
46+
return $data instanceof UnknownCredential;
47+
}
48+
}

src/webauthn/src/Denormalizer/WebauthnSerializerFactory.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public function create(): SerializerInterface
6060
new PublicKeyCredentialOptionsDenormalizer(),
6161
new PublicKeyCredentialSourceDenormalizer(),
6262
new PublicKeyCredentialUserEntityDenormalizer(),
63+
new SignalAllAcceptedCredentialsDenormalizer(),
64+
new SignalCurrentUserDetailsDenormalizer(),
65+
new SignalUnknownCredentialDenormalizer(),
6366
new TrustPathDenormalizer(),
6467
new UidNormalizer(),
6568
new ArrayDenormalizer(),

src/webauthn/src/MetadataService/Service/JsonMetadataService.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@ final class JsonMetadataService implements MetadataService, CanDispatchEvents
3030
/**
3131
* @param string[] $statements
3232
*/
33-
public function __construct(
34-
array $statements,
35-
?SerializerInterface $serializer = null,
36-
) {
33+
public function __construct(array $statements, ?SerializerInterface $serializer = null)
34+
{
3735
$this->dispatcher = new NullEventDispatcher();
3836
$this->serializer = $serializer ?? (new WebauthnSerializerFactory(
3937
AttestationStatementSupportManager::create()
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Webauthn\Signal;
6+
7+
use Webauthn\PublicKeyCredentialDescriptor;
8+
use Webauthn\PublicKeyCredentialRpEntity;
9+
use Webauthn\PublicKeyCredentialUserEntity;
10+
11+
readonly class AllAcceptedCredentials implements Signal
12+
{
13+
/**
14+
* @param PublicKeyCredentialDescriptor[] $allAcceptedCredentials
15+
*/
16+
public function __construct(
17+
public PublicKeyCredentialRpEntity $rp,
18+
public PublicKeyCredentialUserEntity $user,
19+
public array $allAcceptedCredentials,
20+
) {
21+
}
22+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Webauthn\Signal;
6+
7+
use Webauthn\PublicKeyCredentialRpEntity;
8+
use Webauthn\PublicKeyCredentialUserEntity;
9+
10+
readonly class CurrentUserDetails implements Signal
11+
{
12+
public function __construct(
13+
public PublicKeyCredentialRpEntity $rp,
14+
public PublicKeyCredentialUserEntity $user,
15+
) {
16+
}
17+
}

0 commit comments

Comments
 (0)