clusev/tests/Feature/WebauthnOptionsTest.php

68 lines
2.6 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\User;
use App\Models\WebauthnCredential;
use App\Services\DeploymentService;
use App\Services\WebauthnService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class WebauthnOptionsTest extends TestCase
{
use RefreshDatabase;
private function service(string $domain = 'panel.example.com'): WebauthnService
{
$d = $this->mock(DeploymentService::class);
$d->shouldReceive('domain')->andReturn($domain);
return app(WebauthnService::class);
}
public function test_registration_options_use_domain_rpid_and_store_challenge(): void
{
$user = User::factory()->create();
$opts = $this->service()->registrationOptions($user);
$this->assertSame('panel.example.com', data_get($opts, 'rp.id'));
$this->assertNotEmpty(data_get($opts, 'challenge'));
$this->assertNotNull(session('webauthn.register'));
// Target a roaming hardware key (YubiKey) used as a one-touch second factor — not a
// platform/password-manager passkey.
$this->assertSame('cross-platform', data_get($opts, 'authenticatorSelection.authenticatorAttachment'));
$this->assertSame('discouraged', data_get($opts, 'authenticatorSelection.residentKey'));
$this->assertSame('discouraged', data_get($opts, 'authenticatorSelection.userVerification'));
// WebAuthn L3 hint so passkey managers (Bitwarden) defer to the hardware key.
$this->assertSame(['security-key'], data_get($opts, 'hints'));
}
public function test_assertion_options_require_only_user_presence(): void
{
$user = User::factory()->create();
$opts = $this->service()->assertionOptions($user);
// discouraged = a single touch on login, no PIN/biometric prompt.
$this->assertSame('discouraged', data_get($opts, 'userVerification'));
$this->assertSame(['security-key'], data_get($opts, 'hints'));
}
public function test_assertion_options_list_user_credentials(): void
{
$user = User::factory()->create();
WebauthnCredential::create([
'user_id' => $user->id, 'name' => 'k',
'credential_id' => rtrim(strtr(base64_encode('rawid'), '+/', '-_'), '='),
'public_key' => '{}', 'sign_count' => 0,
]);
$opts = $this->service()->assertionOptions($user->fresh());
$this->assertSame('panel.example.com', data_get($opts, 'rpId'));
$this->assertNotEmpty(data_get($opts, 'allowCredentials'));
$this->assertNotNull(session('webauthn.login'));
}
}