diff --git a/composer.json b/composer.json index 55780c10cc8..737aeb0d1fc 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,7 @@ "symfony/yaml": "^7.0.3", "ueberdosis/tiptap-php": "^2.0", "voku/portable-ascii": "^2.0.2", - "web-auth/webauthn-lib": "^5.2", + "web-auth/webauthn-lib": "^5.3@dev", "wilderborn/partyline": "^1.0" }, "require-dev": { diff --git a/src/Auth/WebAuthn/Passkey.php b/src/Auth/WebAuthn/Passkey.php index 322b4c42aa6..df572b2bd6e 100644 --- a/src/Auth/WebAuthn/Passkey.php +++ b/src/Auth/WebAuthn/Passkey.php @@ -7,13 +7,13 @@ use Statamic\Contracts\Auth\Passkey as Contract; use Statamic\Contracts\Auth\User as UserContract; use Statamic\Facades\User; -use Webauthn\PublicKeyCredentialSource; +use Webauthn\CredentialRecord; abstract class Passkey implements Contract { private string $name; private string $user; - private PublicKeyCredentialSource $credential; + private CredentialRecord $credential; private ?Carbon $lastLogin = null; public function id(): string @@ -45,14 +45,14 @@ public function user(): ?UserContract return User::find($this->user); } - public function credential(): PublicKeyCredentialSource + public function credential(): CredentialRecord { return $this->credential; } - public function setCredential(array|PublicKeyCredentialSource $credential): Contract + public function setCredential(array|CredentialRecord $credential): Contract { - $this->credential = $credential instanceof PublicKeyCredentialSource + $this->credential = $credential instanceof CredentialRecord ? $credential : $this->credentialFromArray($credential); @@ -95,15 +95,15 @@ public function __unserialize(array $data): void $this->lastLogin = $data['last_login'] ? Carbon::createFromTimestamp($data['last_login']) : null; } - private function credentialToArray(PublicKeyCredentialSource $credential): array + private function credentialToArray(CredentialRecord $credential): array { $json = app(Serializer::class)->serialize($credential, 'json'); return json_decode($json, true); } - private function credentialFromArray(array $array): PublicKeyCredentialSource + private function credentialFromArray(array $array): CredentialRecord { - return app(Serializer::class)->deserialize(json_encode($array), PublicKeyCredentialSource::class, 'json'); + return app(Serializer::class)->deserialize(json_encode($array), CredentialRecord::class, 'json'); } } diff --git a/src/Auth/WebAuthn/WebAuthn.php b/src/Auth/WebAuthn/WebAuthn.php index f12d8bd8f0b..e8a96cc66ae 100644 --- a/src/Auth/WebAuthn/WebAuthn.php +++ b/src/Auth/WebAuthn/WebAuthn.php @@ -44,7 +44,7 @@ public function validateAssertion(User $user, array $credentials): bool $options = $this->getRequestOptions(session()->pull('webauthn.challenge')); - $publicKeyCredentialSource = $this->assertionResponseValidator->check( + $credentialRecord = $this->assertionResponseValidator->check( $passkey->credential(), $publicKeyCredential->response, $options, @@ -53,7 +53,7 @@ public function validateAssertion(User $user, array $credentials): bool ); $passkey - ->setCredential($publicKeyCredentialSource) + ->setCredential($credentialRecord) ->setLastLogin(now()) ->save(); @@ -94,7 +94,7 @@ public function validateAttestation(User $user, array $credentials, string $name $options = $this->getCreationOptions($user, session()->pull('webauthn.challenge')); - $publicKeyCredentialSource = $this->attestationResponseValidator->check( + $credentialRecord = $this->attestationResponseValidator->check( $publicKeyCredential->response, $options, request()->getHost() @@ -103,7 +103,7 @@ public function validateAttestation(User $user, array $credentials, string $name $passkey = app(Passkey::class) ->setUser($user) ->setName($name) - ->setCredential($publicKeyCredentialSource); + ->setCredential($credentialRecord); $passkey->save(); diff --git a/src/Contracts/Auth/Passkey.php b/src/Contracts/Auth/Passkey.php index 81404728c10..d7d775be2b6 100644 --- a/src/Contracts/Auth/Passkey.php +++ b/src/Contracts/Auth/Passkey.php @@ -3,7 +3,7 @@ namespace Statamic\Contracts\Auth; use Carbon\Carbon; -use Webauthn\PublicKeyCredentialSource; +use Webauthn\CredentialRecord; interface Passkey { @@ -17,9 +17,9 @@ public function user(): ?User; public function setUser(string|User $user): self; - public function credential(): PublicKeyCredentialSource; + public function credential(): CredentialRecord; - public function setCredential(array|PublicKeyCredentialSource $credential): self; + public function setCredential(array|CredentialRecord $credential): self; public function lastLogin(): ?Carbon; diff --git a/tests/Auth/Eloquent/EloquentUserTest.php b/tests/Auth/Eloquent/EloquentUserTest.php index 205c4fa1636..f8c4020746d 100644 --- a/tests/Auth/Eloquent/EloquentUserTest.php +++ b/tests/Auth/Eloquent/EloquentUserTest.php @@ -23,7 +23,7 @@ use Tests\Auth\UserContractTests; use Tests\Preferences\HasPreferencesTests; use Tests\TestCase; -use Webauthn\PublicKeyCredentialSource; +use Webauthn\CredentialRecord; #[Group('2fa')] class EloquentUserTest extends TestCase @@ -342,11 +342,11 @@ public function it_gets_passkeys() $user = $this->user(); $this->assertCount(0, $user->passkeys()); - $mockCredentialA = \Mockery::mock(PublicKeyCredentialSource::class); + $mockCredentialA = \Mockery::mock(CredentialRecord::class); $mockCredentialA->publicKeyCredentialId = 'key-a'; - $mockCredentialB = \Mockery::mock(PublicKeyCredentialSource::class); + $mockCredentialB = \Mockery::mock(CredentialRecord::class); $mockCredentialB->publicKeyCredentialId = 'key-b'; - $mockCredentialC = \Mockery::mock(PublicKeyCredentialSource::class); + $mockCredentialC = \Mockery::mock(CredentialRecord::class); $mockCredentialC->publicKeyCredentialId = 'key-c'; app()->instance(Serializer::class, new class($mockCredentialA, $mockCredentialB, $mockCredentialC) diff --git a/tests/Auth/FileUserTest.php b/tests/Auth/FileUserTest.php index 70b7e8d1a65..ba520fcfd5a 100644 --- a/tests/Auth/FileUserTest.php +++ b/tests/Auth/FileUserTest.php @@ -17,7 +17,7 @@ use Statamic\Support\Arr; use Tests\PreventSavingStacheItemsToDisk; use Tests\TestCase; -use Webauthn\PublicKeyCredentialSource; +use Webauthn\CredentialRecord; #[Group('user')] #[Group('2fa')] @@ -198,9 +198,9 @@ public function it_gets_passkeys() $user = $this->user(); $this->assertCount(0, $user->passkeys()); - $mockCredentialA = \Mockery::mock(PublicKeyCredentialSource::class); + $mockCredentialA = \Mockery::mock(CredentialRecord::class); $mockCredentialA->publicKeyCredentialId = 'key-a'; - $mockCredentialB = \Mockery::mock(PublicKeyCredentialSource::class); + $mockCredentialB = \Mockery::mock(CredentialRecord::class); $mockCredentialB->publicKeyCredentialId = 'key-b'; $user->setPasskeys(collect([ diff --git a/tests/Auth/WebAuthn/EloquentPasskeyTest.php b/tests/Auth/WebAuthn/EloquentPasskeyTest.php index 96ada681df1..487831b3929 100644 --- a/tests/Auth/WebAuthn/EloquentPasskeyTest.php +++ b/tests/Auth/WebAuthn/EloquentPasskeyTest.php @@ -13,7 +13,7 @@ use Statamic\Facades\User; use Symfony\Component\Uid\Uuid; use Tests\TestCase; -use Webauthn\PublicKeyCredentialSource; +use Webauthn\CredentialRecord; use Webauthn\TrustPath\EmptyTrustPath; #[Group('passkeys')] @@ -66,9 +66,9 @@ public static function tearDownAfterClass(): void parent::tearDownAfterClass(); } - private function createTestCredential(string $id = 'test-credential-id-123'): PublicKeyCredentialSource + private function createTestCredential(string $id = 'test-credential-id-123'): CredentialRecord { - return PublicKeyCredentialSource::create( + return CredentialRecord::create( publicKeyCredentialId: $id, type: 'public-key', transports: ['usb', 'nfc'], diff --git a/tests/Auth/WebAuthn/FilePasskeyTest.php b/tests/Auth/WebAuthn/FilePasskeyTest.php index 2743b9997eb..94142922577 100644 --- a/tests/Auth/WebAuthn/FilePasskeyTest.php +++ b/tests/Auth/WebAuthn/FilePasskeyTest.php @@ -10,7 +10,7 @@ use Symfony\Component\Uid\Uuid; use Tests\PreventSavingStacheItemsToDisk; use Tests\TestCase; -use Webauthn\PublicKeyCredentialSource; +use Webauthn\CredentialRecord; use Webauthn\TrustPath\EmptyTrustPath; #[Group('passkeys')] @@ -18,9 +18,9 @@ class FilePasskeyTest extends TestCase { use PreventSavingStacheItemsToDisk; - private function createTestCredential(string $id = 'test-credential-id-123'): PublicKeyCredentialSource + private function createTestCredential(string $id = 'test-credential-id-123'): CredentialRecord { - return PublicKeyCredentialSource::create( + return CredentialRecord::create( publicKeyCredentialId: $id, type: 'public-key', transports: ['usb', 'nfc'], diff --git a/tests/Auth/WebAuthn/PasskeyTest.php b/tests/Auth/WebAuthn/PasskeyTest.php index 73ce924bddd..ba9d71ca019 100644 --- a/tests/Auth/WebAuthn/PasskeyTest.php +++ b/tests/Auth/WebAuthn/PasskeyTest.php @@ -11,7 +11,7 @@ use Symfony\Component\Uid\Uuid; use Tests\PreventSavingStacheItemsToDisk; use Tests\TestCase; -use Webauthn\PublicKeyCredentialSource; +use Webauthn\CredentialRecord; use Webauthn\TrustPath\EmptyTrustPath; #[Group('passkeys')] @@ -19,9 +19,9 @@ class PasskeyTest extends TestCase { use PreventSavingStacheItemsToDisk; - private function createTestCredential(): PublicKeyCredentialSource + private function createTestCredential(): CredentialRecord { - return PublicKeyCredentialSource::create( + return CredentialRecord::create( publicKeyCredentialId: 'test-credential-id-123', type: 'public-key', transports: ['usb', 'nfc'], @@ -45,7 +45,7 @@ public function it_gets_credential() ->setUser($user) ->setCredential($credential); - $this->assertInstanceOf(PublicKeyCredentialSource::class, $passkey->credential()); + $this->assertInstanceOf(CredentialRecord::class, $passkey->credential()); $this->assertEquals('test-credential-id-123', $passkey->credential()->publicKeyCredentialId); $this->assertEquals('public-key', $passkey->credential()->type); } @@ -183,7 +183,7 @@ public function it_unserializes() $this->assertInstanceOf(Passkey::class, $unserialized); $this->assertEquals('My Passkey', $unserialized->name()); $this->assertEquals('test-user', $unserialized->user()->id()); - $this->assertInstanceOf(PublicKeyCredentialSource::class, $unserialized->credential()); + $this->assertInstanceOf(CredentialRecord::class, $unserialized->credential()); $this->assertEquals('test-credential-id-123', $unserialized->credential()->publicKeyCredentialId); $this->assertEquals('2024-01-15 10:30:00', $unserialized->lastLogin()->format('Y-m-d H:i:s')); } diff --git a/tests/Auth/WebAuthn/WebAuthnTest.php b/tests/Auth/WebAuthn/WebAuthnTest.php index d163fe5813d..fdb7d2eb800 100644 --- a/tests/Auth/WebAuthn/WebAuthnTest.php +++ b/tests/Auth/WebAuthn/WebAuthnTest.php @@ -15,10 +15,10 @@ use Webauthn\AuthenticatorAttestationResponseValidator; use Webauthn\AuthenticatorData; use Webauthn\CollectedClientData; +use Webauthn\CredentialRecord; use Webauthn\PublicKeyCredential; use Webauthn\PublicKeyCredentialRequestOptions; use Webauthn\PublicKeyCredentialRpEntity; -use Webauthn\PublicKeyCredentialSource; #[Group('passkeys')] class WebAuthnTest extends TestCase @@ -195,7 +195,7 @@ public function it_validates_assertion_successfully() ); // Mock the passkey - $mockPasskeyCredential = Mockery::mock(PublicKeyCredentialSource::class); + $mockPasskeyCredential = Mockery::mock(CredentialRecord::class); $mockPasskeyCredential->publicKeyCredentialId = 'test-raw-id'; $mockPasskey = Mockery::mock(Passkey::class); @@ -209,7 +209,7 @@ public function it_validates_assertion_successfully() $mockUser->shouldReceive('id')->andReturn('test-user'); $mockUser->shouldReceive('passkeys->first')->andReturn($mockPasskey); - $updatedCredentialSource = Mockery::mock(PublicKeyCredentialSource::class); + $updatedCredentialRecord = Mockery::mock(CredentialRecord::class); $this->mockSerializer ->shouldReceive('deserialize') @@ -219,7 +219,7 @@ public function it_validates_assertion_successfully() $this->mockAssertionValidator ->shouldReceive('check') ->once() - ->andReturn($updatedCredentialSource); + ->andReturn($updatedCredentialRecord); $result = $this->webauthn->validateAssertion($mockUser, $credentials);