Skip to content

Commit 5b957cd

Browse files
authored
feat: adopt webauthn-lib 4.8.0 (#477)
1 parent a3347bc commit 5b957cd

File tree

5 files changed

+65
-49
lines changed

5 files changed

+65
-49
lines changed

composer.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@
2222
"require": {
2323
"php": ">=8.1",
2424
"illuminate/support": "^9.0 || ^10.0",
25+
"phpdocumentor/reflection-docblock": "^5.3",
2526
"psr/http-factory-implementation": "1.0",
27+
"symfony/property-access": "^6.4 || ^7.0",
28+
"symfony/property-info": "^6.4 || ^7.0",
29+
"symfony/serializer": "^6.4 || ^7.0",
2630
"web-auth/cose-lib": "^4.0",
27-
"web-auth/webauthn-lib": "^4.7.1",
31+
"web-auth/webauthn-lib": "^4.8.0",
2832
"web-token/jwt-signature": "^3.0"
2933
},
3034
"conflict": {

src/Services/Webauthn/CredentialAssertionValidator.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
use LaravelWebauthn\Exceptions\ResponseMismatchException;
99
use LaravelWebauthn\Services\Webauthn;
1010
use ParagonIE\ConstantTime\Base64UrlSafe;
11+
use Symfony\Component\Serializer\SerializerInterface;
1112
use Webauthn\AuthenticatorAssertionResponse;
1213
use Webauthn\AuthenticatorAssertionResponseValidator;
1314
use Webauthn\PublicKeyCredential;
14-
use Webauthn\PublicKeyCredentialLoader;
1515
use Webauthn\PublicKeyCredentialRequestOptions;
1616

1717
class CredentialAssertionValidator extends CredentialValidator
1818
{
1919
public function __construct(
2020
Request $request,
2121
Cache $cache,
22-
protected PublicKeyCredentialLoader $loader,
22+
protected SerializerInterface $loader,
2323
protected AuthenticatorAssertionResponseValidator $validator
2424
) {
2525
parent::__construct($request, $cache);
@@ -33,7 +33,8 @@ public function __construct(
3333
public function __invoke(User $user, array $data): bool
3434
{
3535
// Load the data
36-
$publicKeyCredential = $this->loader->loadArray($data);
36+
$content = json_encode($data, flags: JSON_THROW_ON_ERROR);
37+
$publicKeyCredential = $this->loader->deserialize($content, PublicKeyCredential::class, 'json');
3738

3839
// Check the response against the request
3940
$this->validator->check(
@@ -53,9 +54,9 @@ public function __invoke(User $user, array $data): bool
5354
protected function pullPublicKey(User $user): PublicKeyCredentialRequestOptions
5455
{
5556
try {
56-
$value = json_decode($this->cache->pull($this->cacheKey($user)), true, flags: JSON_THROW_ON_ERROR);
57+
$value = $this->cache->pull($this->cacheKey($user));
5758

58-
return PublicKeyCredentialRequestOptions::createFromArray($value);
59+
return $this->loader->deserialize($value, PublicKeyCredentialRequestOptions::class, 'json');
5960
} catch (\Exception $e) {
6061
app('webauthn.log')->debug('Webauthn publickKey deserialize error', ['exception' => $e]);
6162
abort(404);

src/Services/Webauthn/CredentialAttestationValidator.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@
66
use Illuminate\Contracts\Cache\Repository as Cache;
77
use Illuminate\Http\Request;
88
use LaravelWebauthn\Exceptions\ResponseMismatchException;
9+
use Symfony\Component\Serializer\SerializerInterface;
910
use Webauthn\AuthenticatorAttestationResponse;
1011
use Webauthn\AuthenticatorAttestationResponseValidator;
1112
use Webauthn\PublicKeyCredential;
1213
use Webauthn\PublicKeyCredentialCreationOptions;
13-
use Webauthn\PublicKeyCredentialLoader;
1414
use Webauthn\PublicKeyCredentialSource;
1515

1616
class CredentialAttestationValidator extends CredentialValidator
1717
{
1818
public function __construct(
1919
Request $request,
2020
Cache $cache,
21-
protected PublicKeyCredentialLoader $loader,
21+
protected SerializerInterface $loader,
2222
protected AuthenticatorAttestationResponseValidator $validator
2323
) {
2424
parent::__construct($request, $cache);
@@ -32,7 +32,8 @@ public function __construct(
3232
public function __invoke(User $user, array $data): PublicKeyCredentialSource
3333
{
3434
// Load the data
35-
$publicKeyCredential = $this->loader->loadArray($data);
35+
$content = json_encode($data, flags: JSON_THROW_ON_ERROR);
36+
$publicKeyCredential = $this->loader->deserialize($content, PublicKeyCredential::class, 'json');
3637

3738
// Check the response against the request
3839
return $this->validator->check(
@@ -48,9 +49,9 @@ public function __invoke(User $user, array $data): PublicKeyCredentialSource
4849
protected function pullPublicKey(User $user): PublicKeyCredentialCreationOptions
4950
{
5051
try {
51-
$value = json_decode($this->cache->pull($this->cacheKey($user)), true, flags: JSON_THROW_ON_ERROR);
52+
$value = $this->cache->pull($this->cacheKey($user));
5253

53-
return PublicKeyCredentialCreationOptions::createFromArray($value);
54+
return $this->loader->deserialize($value, PublicKeyCredentialCreationOptions::class, 'json');
5455
} catch (\Exception $e) {
5556
app('webauthn.log')->debug('Webauthn publicKey deserialize error', ['exception' => $e]);
5657
abort(404);

src/WebauthnServiceProvider.php

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
use Psr\Http\Message\StreamFactoryInterface;
4040
use Psr\Http\Message\UploadedFileFactoryInterface;
4141
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
42+
use Symfony\Component\Serializer\SerializerInterface;
4243
use Webauthn\AttestationStatement\AndroidKeyAttestationStatementSupport;
4344
use Webauthn\AttestationStatement\AndroidSafetyNetAttestationStatementSupport;
4445
use Webauthn\AttestationStatement\AppleAttestationStatementSupport;
@@ -52,9 +53,9 @@
5253
use Webauthn\AuthenticatorAssertionResponseValidator;
5354
use Webauthn\AuthenticatorAttestationResponseValidator;
5455
use Webauthn\AuthenticatorSelectionCriteria;
56+
use Webauthn\CeremonyStep\CeremonyStepManagerFactory;
5557
use Webauthn\Counter\CounterChecker;
5658
use Webauthn\Counter\ThrowExceptionIfInvalid;
57-
use Webauthn\PublicKeyCredentialLoader;
5859
use Webauthn\PublicKeyCredentialRpEntity;
5960

6061
class WebauthnServiceProvider extends ServiceProvider
@@ -188,15 +189,24 @@ protected function bindWebAuthnPackage(): void
188189
), fn (AuthenticatorAttestationResponseValidator $responseValidator) => $responseValidator->setLogger($app['webauthn.log'])
189190
)
190191
);
192+
$this->app->bind(
193+
CeremonyStepManagerFactory::class,
194+
fn ($app) => tap(new CeremonyStepManagerFactory, function (CeremonyStepManagerFactory $factory) use ($app) {
195+
$factory->setExtensionOutputCheckerHandler($app[ExtensionOutputCheckerHandler::class]);
196+
$factory->setAlgorithmManager($app[CoseAlgorithmManager::class]);
197+
$factory->setCounterChecker($app[CounterChecker::class]);
198+
})
199+
);
191200
$this->app->bind(
192201
AuthenticatorAssertionResponseValidator::class,
193202
fn ($app) => tap((new AuthenticatorAssertionResponseValidator(
194203
null,
195204
null,
196205
$app[ExtensionOutputCheckerHandler::class],
197-
$app[CoseAlgorithmManager::class]
198-
))
199-
->setCounterChecker($app[CounterChecker::class]), fn (AuthenticatorAssertionResponseValidator $responseValidator) => $responseValidator->setLogger($app['webauthn.log'])
206+
$app[CoseAlgorithmManager::class],
207+
null,
208+
($app[CeremonyStepManagerFactory::class])->requestCeremony()
209+
)), fn (AuthenticatorAssertionResponseValidator $responseValidator) => $responseValidator->setLogger($app['webauthn.log'])
200210
)
201211
);
202212
$this->app->bind(
@@ -207,7 +217,6 @@ protected function bindWebAuthnPackage(): void
207217
$app['config']->get('webauthn.userless')
208218
)
209219
);
210-
211220
$this->app->bind(
212221
PublicKeyCredentialRpEntity::class,
213222
fn ($app) => new PublicKeyCredentialRpEntity(
@@ -216,14 +225,6 @@ protected function bindWebAuthnPackage(): void
216225
$app['config']->get('webauthn.icon')
217226
)
218227
);
219-
$this->app->bind(
220-
PublicKeyCredentialLoader::class,
221-
fn ($app) => tap(new PublicKeyCredentialLoader(
222-
$app[AttestationObjectLoader::class]
223-
), fn (PublicKeyCredentialLoader $loader) => $loader->setLogger($app['webauthn.log'])
224-
)
225-
);
226-
227228
$this->app->bind(
228229
CoseAlgorithmManager::class,
229230
fn ($app) => $app[CoseAlgorithmManagerFactory::class]
@@ -256,6 +257,10 @@ protected function bindWebAuthnPackage(): void
256257
}
257258
})
258259
);
260+
$this->app->bind(
261+
SerializerInterface::class,
262+
fn ($app) => (new \Webauthn\Denormalizer\WebauthnSerializerFactory($app[AttestationStatementSupportManager::class]))->create()
263+
);
259264
}
260265

261266
/**

tests/Unit/Services/WebauthnTest.php

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use CBOR\ListObject;
66
use CBOR\MapItem;
77
use CBOR\MapObject;
8+
use CBOR\NegativeIntegerObject;
89
use CBOR\TextStringObject;
910
use Illuminate\Database\Eloquent\ModelNotFoundException;
1011
use Illuminate\Foundation\Testing\DatabaseTransactions;
@@ -46,30 +47,30 @@ public function test_get_register_data()
4647
/**
4748
* @test
4849
*/
49-
// public function test_do_register_data()
50-
// {
51-
// $user = $this->signIn();
52-
53-
// $publicKey = $this->app[PrepareCreationData::class]($user);
54-
// $this->assertInstanceOf(\Webauthn\PublicKeyCredentialCreationOptions::class, $publicKey);
55-
56-
// $data = $this->getAttestationData($publicKey);
57-
58-
// $this->app[ValidateKeyCreation::class]($user, $data, 'name');
59-
60-
// $this->assertDatabaseHas('webauthn_keys', [
61-
// 'user_id' => $user->getAuthIdentifier(),
62-
// 'name' => 'name',
63-
// 'credentialId' => 'MA==',
64-
// 'type' => 'public-key',
65-
// 'transports' => '[]',
66-
// 'attestationType' => 'none',
67-
// 'trustPath' => '{"type":"Webauthn\\\\TrustPath\\\\EmptyTrustPath"}',
68-
// 'aaguid' => '00000000-0000-0000-0000-000000000000',
69-
// 'credentialPublicKey' => 'oWNrZXlldmFsdWU=',
70-
// 'counter' => '1',
71-
// ]);
72-
// }
50+
public function test_do_register_data()
51+
{
52+
$user = $this->signIn();
53+
54+
$publicKey = $this->app[PrepareCreationData::class]($user);
55+
$this->assertInstanceOf(\Webauthn\PublicKeyCredentialCreationOptions::class, $publicKey);
56+
57+
$data = $this->getAttestationData($publicKey);
58+
59+
$this->app[ValidateKeyCreation::class]($user, $data, 'name');
60+
61+
$this->assertDatabaseHas('webauthn_keys', [
62+
'user_id' => $user->getAuthIdentifier(),
63+
'name' => 'name',
64+
'credentialId' => 'MA==',
65+
'type' => 'public-key',
66+
'transports' => '[]',
67+
'attestationType' => 'none',
68+
'trustPath' => '{"type":"Webauthn\\\\TrustPath\\\\EmptyTrustPath"}',
69+
'aaguid' => '30303030-3030-3030-3030-303030303030',
70+
'credentialPublicKey' => 'omExZXZhbHVlYTMm',
71+
'counter' => '1',
72+
]);
73+
}
7374

7475
/**
7576
* @test
@@ -141,9 +142,13 @@ private function getAttestationData($publicKey)
141142
pack('n', 1).'0'. // credentialLength
142143
((string) new MapObject([
143144
new MapItem(
144-
new TextStringObject('key'),
145+
new TextStringObject('1'),
145146
new TextStringObject('value')
146147
),
148+
new MapItem(
149+
new TextStringObject('3'),
150+
new NegativeIntegerObject(6, null)
151+
),
147152
])) // credentialPublicKey
148153
)
149154
),

0 commit comments

Comments
 (0)