Files
webauthn/tests/Http/Requests/AssertionRequestTest.php
2022-06-14 05:17:04 -04:00

230 lines
7.4 KiB
PHP

<?php
namespace Tests\Http\Requests;
use Illuminate\Foundation\Auth\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use Laragear\WebAuthn\Assertion\Creator\AssertionCreation;
use Laragear\WebAuthn\Assertion\Creator\AssertionCreator;
use Laragear\WebAuthn\Challenge;
use Laragear\WebAuthn\Http\Requests\AssertionRequest;
use Laragear\WebAuthn\JsonTransport;
use Tests\FakeAuthenticator;
use Tests\Stubs\WebAuthnAuthenticatableUser;
use Tests\TestCase;
use function config;
use function session;
use function strlen;
class AssertionRequestTest extends TestCase
{
protected function afterRefreshingDatabase(): void
{
WebAuthnAuthenticatableUser::forceCreate([
'name' => FakeAuthenticator::ATTESTATION_USER['displayName'],
'email' => FakeAuthenticator::ATTESTATION_USER['name'],
'password' => 'test_password',
]);
}
protected function defineEnvironment($app): void
{
$app->make('config')->set('auth.providers.users.driver', 'eloquent-webauthn');
$app->make('config')->set('auth.providers.users.model', WebAuthnAuthenticatableUser::class);
}
public function test_creates_assertion(): void
{
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->toVerify();
});
$this->postJson('test')
->assertSessionHas('_webauthn', function (Challenge $challenge): bool {
return !$challenge->verify;
})
->assertJson([
'timeout' => 60000,
'challenge' => session('_webauthn')->data->toBase64Url()
]);
}
public function test_uses_custom_timeout(): void
{
config(['webauthn.challenge.timeout' => 120]);
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->toVerify();
});
$this->postJson('test')
->assertJson([
'timeout' => 120000,
'challenge' => session('_webauthn')->data->toBase64Url()
]);
}
public function test_uses_custom_length(): void
{
config(['webauthn.challenge.bytes' => 32]);
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->toVerify();
});
$this->postJson('test')
->assertJson([
'timeout' => 60000,
'challenge' => session('_webauthn')->data->toBase64Url()
]);
static::assertSame(64, strlen(session('_webauthn')->data->toHex()));
}
public function test_uses_custom_session_key(): void
{
config(['webauthn.challenge.key' => 'foo']);
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->toVerify();
});
$this->postJson('test')->assertSessionHas('foo');
}
public function test_uses_custom_guard(): void
{
$guard = Auth::guard('web');
Auth::partialMock()->expects('guard')->with('foo')->andReturn($guard);
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->guard('foo')->toVerify(['email' => FakeAuthenticator::ATTESTATION_USER['name']]);
});
$this->postJson('test')
->assertOk()
->assertJson([
'timeout' => 60000,
'challenge' => session('_webauthn')->data->toBase64Url()
]);
}
public function test_guard_fails_if_user_not_webauthn_authenticatable(): void
{
config(['auth.providers.users.driver' => 'eloquent']);
config(['auth.providers.users.model' => User::class]);
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->guard('web')->toVerify(['email' => FakeAuthenticator::ATTESTATION_USER['name']]);
});
$this->postJson('test')
->assertStatus(500)
->assertSee('The user found for the [web] auth guard is not an instance of [WebAuthnAuthenticatable].');
}
public function test_uses_fast_login(): void
{
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->fastLogin()->toVerify();
});
$this->postJson('test')->assertJson([
'timeout' => 60000,
'userVerification' => 'discouraged',
'challenge' => session('_webauthn')->data->toBase64Url()
]);
static::assertFalse(session('_webauthn')->verify);
}
public function test_uses_secure_login(): void
{
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->secureLogin()->toVerify();
});
$this->postJson('test')->assertJson([
'timeout' => 60000,
'userVerification' => 'required',
'challenge' => session('_webauthn')->data->toBase64Url()
]);
static::assertTrue(session('_webauthn')->verify);
}
public function test_uses_verify_with_already_instanced_user(): void
{
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->toVerify(WebAuthnAuthenticatableUser::find(1));
});
$creator = $this->mock(AssertionCreator::class);
$creator->expects('send')->withArgs(function (AssertionCreation $creation): bool {
return $creation->user->getKey() === 1;
})
->andReturnSelf();
$creator->expects('then')->andReturn(new JsonTransport());
$this->postJson('test')->assertOk();
}
public function test_uses_verify_with_user_id(): void
{
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->toVerify(1);
});
$creator = $this->mock(AssertionCreator::class);
$creator->expects('send')->withArgs(function (AssertionCreation $creation): bool {
return $creation->user->getKey() === 1;
})
->andReturnSelf();
$creator->expects('then')->andReturn(new JsonTransport());
$this->postJson('test')->assertOk();
}
public function test_uses_verify_with_bad_id_returning_null_user(): void
{
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->toVerify(99);
});
$creator = $this->mock(AssertionCreator::class);
$creator->expects('send')->withArgs(function (AssertionCreation $creation): bool {
return ! $creation->user;
})
->andReturnSelf();
$creator->expects('then')->andReturn(new JsonTransport());
$this->postJson('test')->assertOk();
}
public function test_uses_verify_with_bad_credentials_returning_null_user(): void
{
Route::middleware('web')->post('test', function (AssertionRequest $request) {
return $request->toVerify(['email' => 'invalid@email.com']);
});
$creator = $this->mock(AssertionCreator::class);
$creator->expects('send')->withArgs(function (AssertionCreation $creation): bool {
return ! $creation->user;
})
->andReturnSelf();
$creator->expects('then')->andReturn(new JsonTransport());
$this->postJson('test')->assertOk();
}
}