178 lines
5.4 KiB
PHP
178 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Routing\Middleware\ThrottleRequestsWithRedis;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Tests\TestCase;
|
|
|
|
class ApiAuthenticationTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
protected $user;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$this->user = User::factory()->create([
|
|
'password' => Hash::make('mypassword')
|
|
]);
|
|
|
|
$this->user->usernames()->save($this->user->defaultUsername);
|
|
$this->user->defaultUsername->username = 'johndoe';
|
|
$this->user->defaultUsername->save();
|
|
}
|
|
|
|
/** @test */
|
|
public function user_can_retreive_valid_access_token()
|
|
{
|
|
$this->withoutMiddleware(ThrottleRequestsWithRedis::class);
|
|
|
|
$response = $this->json('POST', '/api/auth/login', [
|
|
'username' => 'johndoe',
|
|
'password' => 'mypassword',
|
|
'device_name' => 'Firefox'
|
|
]);
|
|
|
|
$response->assertSuccessful();
|
|
$this->assertEquals($this->user->tokens[0]->token, hash('sha256', $response->json()['api_key']));
|
|
}
|
|
|
|
/** @test */
|
|
public function user_password_must_be_correct_to_get_access_token()
|
|
{
|
|
$this->withoutMiddleware(ThrottleRequestsWithRedis::class);
|
|
|
|
$response = $this->json('POST', '/api/auth/login', [
|
|
'username' => 'johndoe',
|
|
'password' => 'myincorrectpassword',
|
|
'device_name' => 'Firefox'
|
|
]);
|
|
|
|
$response->assertUnauthorized();
|
|
}
|
|
|
|
/** @test */
|
|
public function user_must_exist_to_get_access_token()
|
|
{
|
|
$this->withoutMiddleware(ThrottleRequestsWithRedis::class);
|
|
|
|
$response = $this->json('POST', '/api/auth/login', [
|
|
'username' => 'doesnotexist',
|
|
'password' => 'mypassword',
|
|
'device_name' => 'Firefox'
|
|
]);
|
|
|
|
$response->assertUnauthorized();
|
|
$response->assertExactJson(['error' => 'The provided credentials are incorrect']);
|
|
}
|
|
|
|
/** @test */
|
|
public function user_is_throttled_by_middleware_for_too_many_requests()
|
|
{
|
|
$this->json('POST', '/api/auth/login', [
|
|
'username' => 'johndoe',
|
|
'password' => 'incorrect1',
|
|
'device_name' => 'Firefox'
|
|
]);
|
|
|
|
$this->json('POST', '/api/auth/login', [
|
|
'username' => 'johndoe',
|
|
'password' => 'incorrect2',
|
|
'device_name' => 'Firefox'
|
|
]);
|
|
|
|
$this->json('POST', '/api/auth/login', [
|
|
'username' => 'johndoe',
|
|
'password' => 'incorrect3',
|
|
'device_name' => 'Firefox'
|
|
]);
|
|
|
|
$response = $this->json('POST', '/api/auth/login', [
|
|
'username' => 'johndoe',
|
|
'password' => 'incorrect4',
|
|
'device_name' => 'Firefox'
|
|
]);
|
|
|
|
$response->assertStatus(429);
|
|
}
|
|
|
|
/** @test */
|
|
public function user_cannot_get_access_token_with_webauthn_enabled()
|
|
{
|
|
$this->withoutMiddleware(ThrottleRequestsWithRedis::class);
|
|
|
|
$this->user->webauthnKeys()->create([
|
|
'name' => 'key',
|
|
'enabled' => true,
|
|
'credentialId' => 'xyz',
|
|
'type' => 'public-key',
|
|
'transports' => [],
|
|
'attestationType' => 'none',
|
|
'trustPath' => '{"type":"Webauthn\\TrustPath\\EmptyTrustPath"}',
|
|
'aaguid' => '00000000-0000-0000-0000-000000000000',
|
|
'credentialPublicKey' => 'xyz',
|
|
'counter' => 0
|
|
]);
|
|
|
|
$response = $this->json('POST', '/api/auth/login', [
|
|
'username' => 'johndoe',
|
|
'password' => 'mypassword',
|
|
'device_name' => 'Firefox'
|
|
]);
|
|
|
|
$response->assertForbidden();
|
|
$response->assertExactJson(['error' => 'WebAuthn authentication is not currently supported from the extension or mobile apps, please use an API key to login instead']);
|
|
}
|
|
|
|
/** @test */
|
|
public function user_must_provide_correct_otp_if_enabled()
|
|
{
|
|
$this->withoutMiddleware(ThrottleRequestsWithRedis::class);
|
|
|
|
$secret = app('pragmarx.google2fa')->generateSecretKey();
|
|
$this->user->update([
|
|
'two_factor_secret' => $secret,
|
|
'two_factor_enabled' => true
|
|
]);
|
|
|
|
$response = $this->json('POST', '/api/auth/login', [
|
|
'username' => 'johndoe',
|
|
'password' => 'mypassword',
|
|
'device_name' => 'Firefox'
|
|
]);
|
|
|
|
$response->assertStatus(422);
|
|
|
|
$mfaKey = $response->json()['mfa_key'];
|
|
$csrfToken = $response->json()['csrf_token'];
|
|
$this->assertNotNull($mfaKey);
|
|
$this->assertNotNull($csrfToken);
|
|
|
|
$response2 = $this->withHeaders([
|
|
'X-CSRF-TOKEN' => $csrfToken,
|
|
])->json('POST', '/api/auth/mfa', [
|
|
'mfa_key' => $mfaKey,
|
|
'otp' => '000000',
|
|
'device_name' => 'Firefox'
|
|
]);
|
|
|
|
$response2->assertUnauthorized();
|
|
$response2->assertExactJson(['error' => 'The \'One Time Password\' typed was wrong']);
|
|
|
|
$response3 = $this->withHeaders([
|
|
'X-CSRF-TOKEN' => $csrfToken,
|
|
])->json('POST', '/api/auth/mfa', [
|
|
'mfa_key' => $mfaKey,
|
|
'otp' => app('pragmarx.google2fa')->getCurrentOtp($secret),
|
|
'device_name' => 'Firefox'
|
|
]);
|
|
|
|
$response3->assertSuccessful();
|
|
$this->assertEquals($this->user->tokens[0]->token, hash('sha256', $response3->json()['api_key']));
|
|
}
|
|
}
|