Changeset View
Changeset View
Standalone View
Standalone View
src/tests/Feature/Controller/AuthTest.php
<?php | <?php | ||||
namespace Tests\Feature\Controller; | namespace Tests\Feature\Controller; | ||||
use App\Domain; | use App\Domain; | ||||
use App\User; | use App\User; | ||||
use Tests\TestCase; | use Tests\TestCase; | ||||
class AuthTest extends TestCase | class AuthTest extends TestCase | ||||
{ | { | ||||
private $expectedExpiry; | |||||
/** | |||||
* Reset all authentication guards to clear any cache users | |||||
*/ | |||||
machniak: This method might be useful in other places. How about moving it to TestCase or TestCaseTrait? | |||||
Done Inline ActionsI figured we can do that as soon as we need it someplace. mollekopf: I figured we can do that as soon as we need it someplace. | |||||
protected function resetAuth() | |||||
{ | |||||
$guards = array_keys(config('auth.guards')); | |||||
foreach ($guards as $guard) { | |||||
$guard = $this->app['auth']->guard($guard); | |||||
if ($guard instanceof \Illuminate\Auth\SessionGuard) { | |||||
$guard->logout(); | |||||
} | |||||
} | |||||
$protectedProperty = new \ReflectionProperty($this->app['auth'], 'guards'); | |||||
$protectedProperty->setAccessible(true); | |||||
$protectedProperty->setValue($this->app['auth'], []); | |||||
} | |||||
/** | /** | ||||
* {@inheritDoc} | * {@inheritDoc} | ||||
*/ | */ | ||||
public function setUp(): void | public function setUp(): void | ||||
{ | { | ||||
parent::setUp(); | parent::setUp(); | ||||
$this->deleteTestUser('UsersControllerTest1@userscontroller.com'); | $this->deleteTestUser('UsersControllerTest1@userscontroller.com'); | ||||
$this->deleteTestDomain('userscontroller.com'); | $this->deleteTestDomain('userscontroller.com'); | ||||
$this->expectedExpiry = \config('auth.token_expiry_minutes') * 60; | |||||
} | } | ||||
/** | /** | ||||
* {@inheritDoc} | * {@inheritDoc} | ||||
*/ | */ | ||||
public function tearDown(): void | public function tearDown(): void | ||||
{ | { | ||||
$this->deleteTestUser('UsersControllerTest1@userscontroller.com'); | $this->deleteTestUser('UsersControllerTest1@userscontroller.com'); | ||||
Show All 24 Lines | public function testInfo(): void | ||||
$this->assertTrue(is_array($json['statusInfo'])); | $this->assertTrue(is_array($json['statusInfo'])); | ||||
$this->assertTrue(is_array($json['settings'])); | $this->assertTrue(is_array($json['settings'])); | ||||
$this->assertTrue(is_array($json['aliases'])); | $this->assertTrue(is_array($json['aliases'])); | ||||
$this->assertTrue(!isset($json['access_token'])); | $this->assertTrue(!isset($json['access_token'])); | ||||
// Note: Details of the content are tested in testUserResponse() | // Note: Details of the content are tested in testUserResponse() | ||||
// Test token refresh via the info request | // Test token refresh via the info request | ||||
// First we log in as we need the token (actingAs() will not work) | // First we log in to get the refresh token | ||||
$post = ['email' => 'john@kolab.org', 'password' => 'simple123']; | $post = ['email' => 'john@kolab.org', 'password' => 'simple123']; | ||||
$user = $this->getTestUser('john@kolab.org'); | |||||
$response = $this->post("api/auth/login", $post); | $response = $this->post("api/auth/login", $post); | ||||
$json = $response->json(); | $json = $response->json(); | ||||
$response = $this->withHeaders(['Authorization' => 'Bearer ' . $json['access_token']]) | $response = $this->actingAs($user) | ||||
->get("api/auth/info?refresh_token=1"); | ->post("api/auth/info?refresh=1", ['refresh_token' => $json['refresh_token']]); | ||||
Done Inline ActionsIf actingAs() then do we need withHeaders()? machniak: If actingAs() then do we need withHeaders()? | |||||
Done Inline ActionsNope mollekopf: Nope | |||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$json = $response->json(); | $json = $response->json(); | ||||
$this->assertEquals('john@kolab.org', $json['email']); | $this->assertEquals('john@kolab.org', $json['email']); | ||||
$this->assertTrue(is_array($json['statusInfo'])); | $this->assertTrue(is_array($json['statusInfo'])); | ||||
$this->assertTrue(is_array($json['settings'])); | $this->assertTrue(is_array($json['settings'])); | ||||
$this->assertTrue(is_array($json['aliases'])); | $this->assertTrue(is_array($json['aliases'])); | ||||
Show All 29 Lines | public function testLogin(): string | ||||
// Valid user+password | // Valid user+password | ||||
$user = $this->getTestUser('john@kolab.org'); | $user = $this->getTestUser('john@kolab.org'); | ||||
$post = ['email' => 'john@kolab.org', 'password' => 'simple123']; | $post = ['email' => 'john@kolab.org', 'password' => 'simple123']; | ||||
$response = $this->post("api/auth/login", $post); | $response = $this->post("api/auth/login", $post); | ||||
$json = $response->json(); | $json = $response->json(); | ||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$this->assertTrue(!empty($json['access_token'])); | $this->assertTrue(!empty($json['access_token'])); | ||||
$this->assertEquals(\config('jwt.ttl') * 60, $json['expires_in']); | $this->assertTrue( | ||||
($this->expectedExpiry - 5) < $json['expires_in'] && | |||||
$json['expires_in'] < ($this->expectedExpiry + 5) | |||||
); | |||||
$this->assertEquals('bearer', $json['token_type']); | $this->assertEquals('bearer', $json['token_type']); | ||||
$this->assertEquals($user->id, $json['id']); | $this->assertEquals($user->id, $json['id']); | ||||
$this->assertEquals($user->email, $json['email']); | $this->assertEquals($user->email, $json['email']); | ||||
$this->assertTrue(is_array($json['statusInfo'])); | $this->assertTrue(is_array($json['statusInfo'])); | ||||
$this->assertTrue(is_array($json['settings'])); | $this->assertTrue(is_array($json['settings'])); | ||||
$this->assertTrue(is_array($json['aliases'])); | $this->assertTrue(is_array($json['aliases'])); | ||||
// Valid user+password (upper-case) | // Valid user+password (upper-case) | ||||
$post = ['email' => 'John@Kolab.org', 'password' => 'simple123']; | $post = ['email' => 'John@Kolab.org', 'password' => 'simple123']; | ||||
$response = $this->post("api/auth/login", $post); | $response = $this->post("api/auth/login", $post); | ||||
$json = $response->json(); | $json = $response->json(); | ||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$this->assertTrue(!empty($json['access_token'])); | $this->assertTrue(!empty($json['access_token'])); | ||||
$this->assertEquals(\config('jwt.ttl') * 60, $json['expires_in']); | $this->assertTrue( | ||||
($this->expectedExpiry - 5) < $json['expires_in'] && | |||||
$json['expires_in'] < ($this->expectedExpiry + 5) | |||||
); | |||||
Done Inline ActionsSo, maybe make the value configurable. machniak: So, maybe make the value configurable. | |||||
$this->assertEquals('bearer', $json['token_type']); | $this->assertEquals('bearer', $json['token_type']); | ||||
// TODO: We have browser tests for 2FA but we should probably also test it here | // TODO: We have browser tests for 2FA but we should probably also test it here | ||||
return $json['access_token']; | return $json['access_token']; | ||||
} | } | ||||
/** | /** | ||||
* Test /api/auth/logout | * Test /api/auth/logout | ||||
* | * | ||||
* @depends testLogin | * @depends testLogin | ||||
*/ | */ | ||||
public function testLogout($token): void | public function testLogout($token): void | ||||
{ | { | ||||
// Request with no token, testing that it requires auth | // Request with no token, testing that it requires auth | ||||
$response = $this->post("api/auth/logout"); | $response = $this->post("api/auth/logout"); | ||||
$response->assertStatus(401); | $response->assertStatus(401); | ||||
// Test the same using JSON mode | // Test the same using JSON mode | ||||
$response = $this->json('POST', "api/auth/logout", []); | $response = $this->json('POST', "api/auth/logout", []); | ||||
$response->assertStatus(401); | $response->assertStatus(401); | ||||
// Request with invalid token | |||||
$response = $this->withHeaders(['Authorization' => 'Bearer ' . "foobar"])->post("api/auth/logout"); | |||||
$response->assertStatus(401); | |||||
// Request with valid token | // Request with valid token | ||||
$response = $this->withHeaders(['Authorization' => 'Bearer ' . $token])->post("api/auth/logout"); | $response = $this->withHeaders(['Authorization' => 'Bearer ' . $token])->post("api/auth/logout"); | ||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$json = $response->json(); | $json = $response->json(); | ||||
$this->assertEquals('success', $json['status']); | $this->assertEquals('success', $json['status']); | ||||
$this->assertEquals('Successfully logged out.', $json['message']); | $this->assertEquals('Successfully logged out.', $json['message']); | ||||
$this->resetAuth(); | |||||
// Check if it really destroyed the token? | // Check if it really destroyed the token? | ||||
$response = $this->withHeaders(['Authorization' => 'Bearer ' . $token])->get("api/auth/info"); | $response = $this->withHeaders(['Authorization' => 'Bearer ' . $token])->get("api/auth/info"); | ||||
$response->assertStatus(401); | $response->assertStatus(401); | ||||
} | } | ||||
/** | /** | ||||
* Test /api/auth/refresh | * Test /api/auth/refresh | ||||
Show All 10 Lines | public function testRefresh(): void | ||||
// Login the user to get a valid token | // Login the user to get a valid token | ||||
$post = ['email' => 'john@kolab.org', 'password' => 'simple123']; | $post = ['email' => 'john@kolab.org', 'password' => 'simple123']; | ||||
$response = $this->post("api/auth/login", $post); | $response = $this->post("api/auth/login", $post); | ||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$json = $response->json(); | $json = $response->json(); | ||||
$token = $json['access_token']; | $token = $json['access_token']; | ||||
$user = $this->getTestUser('john@kolab.org'); | |||||
// Request with a valid token | // Request with a valid token | ||||
$response = $this->withHeaders(['Authorization' => 'Bearer ' . $token])->post("api/auth/refresh"); | $response = $this->actingAs($user)->post("api/auth/refresh", ['refresh_token' => $json['refresh_token']]); | ||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
$json = $response->json(); | $json = $response->json(); | ||||
$this->assertTrue(!empty($json['access_token'])); | $this->assertTrue(!empty($json['access_token'])); | ||||
$this->assertTrue($json['access_token'] != $token); | $this->assertTrue($json['access_token'] != $token); | ||||
$this->assertEquals(\config('jwt.ttl') * 60, $json['expires_in']); | $this->assertTrue( | ||||
($this->expectedExpiry - 5) < $json['expires_in'] && | |||||
$json['expires_in'] < ($this->expectedExpiry + 5) | |||||
); | |||||
$this->assertEquals('bearer', $json['token_type']); | $this->assertEquals('bearer', $json['token_type']); | ||||
$new_token = $json['access_token']; | $new_token = $json['access_token']; | ||||
// TODO: Shall we invalidate the old token? | // TODO: Shall we invalidate the old token? | ||||
// And if the new token is working | // And if the new token is working | ||||
$response = $this->withHeaders(['Authorization' => 'Bearer ' . $new_token])->get("api/auth/info"); | $response = $this->withHeaders(['Authorization' => 'Bearer ' . $new_token])->get("api/auth/info"); | ||||
$response->assertStatus(200); | $response->assertStatus(200); | ||||
} | } | ||||
} | } |
This method might be useful in other places. How about moving it to TestCase or TestCaseTrait?