-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Update LoginResponse to implement LoginResponseInterface * Updated test namespace * Overwritten OpenIDConnectClient redirect function to use Laravel abort method * Login tests * Add response test
- Loading branch information
1 parent
7fdff54
commit cbb4e9f
Showing
5 changed files
with
323 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace MinVWS\OpenIDConnectLaravel\Tests\Feature\Http\Controllers; | ||
|
||
use Illuminate\Support\Facades\Http; | ||
use MinVWS\OpenIDConnectLaravel\OpenIDConfiguration\OpenIDConfiguration; | ||
use MinVWS\OpenIDConnectLaravel\OpenIDConfiguration\OpenIDConfigurationLoader; | ||
use MinVWS\OpenIDConnectLaravel\OpenIDConnectClient; | ||
use MinVWS\OpenIDConnectLaravel\Tests\TestCase; | ||
use Mockery; | ||
|
||
class LoginControllerTest extends TestCase | ||
{ | ||
public function setUp(): void | ||
{ | ||
parent::setUp(); | ||
|
||
// Support for running tests with Laravel 8 | ||
if (method_exists(Http::class, 'preventStrayRequests')) { | ||
Http::preventStrayRequests(); | ||
} | ||
} | ||
|
||
public function testLoginRouteRedirectsToAuthorizeUrlOfProvider(): void | ||
{ | ||
$this->mockOpenIDConfigurationLoader(); | ||
|
||
config()->set('oidc.client_id', 'test-client-id'); | ||
|
||
$response = $this->get(route('oidc.login')); | ||
$response | ||
->assertStatus(302) | ||
->assertRedirectContains("https://provider.rdobeheer.nl/authorize") | ||
->assertRedirectContains('test-client-id'); | ||
} | ||
|
||
public function testLoginRouteReturnsUserInfoWitchMockedClient(): void | ||
{ | ||
$mockClient = Mockery::mock(OpenIDConnectClient::class); | ||
$mockClient | ||
->shouldReceive('authenticate') | ||
->once(); | ||
|
||
$mockClient | ||
->shouldReceive('requestUserInfo') | ||
->andReturn((object) [ | ||
'sub' => 'test-sub', | ||
'name' => 'test-name', | ||
'email' => 'test-email', | ||
]); | ||
|
||
$this->app->instance(OpenIDConnectClient::class, $mockClient); | ||
|
||
$response = $this->get(route('oidc.login')); | ||
$response | ||
->assertJson([ | ||
'userInfo' => [ | ||
'sub' => 'test-sub', | ||
'name' => 'test-name', | ||
'email' => 'test-email', | ||
], | ||
]); | ||
} | ||
|
||
protected function mockOpenIDConfigurationLoader(): void | ||
{ | ||
$mock = Mockery::mock(OpenIDConfigurationLoader::class); | ||
$mock | ||
->shouldReceive('getConfiguration') | ||
->andReturn($this->exampleOpenIDConfiguration()); | ||
|
||
$this->app->instance(OpenIDConfigurationLoader::class, $mock); | ||
} | ||
|
||
protected function exampleOpenIDConfiguration(): OpenIDConfiguration | ||
{ | ||
return new OpenIDConfiguration( | ||
version: "3.0", | ||
tokenEndpointAuthMethodsSupported: ["none"], | ||
claimsParameterSupported: true, | ||
requestParameterSupported: false, | ||
requestUriParameterSupported: true, | ||
requireRequestUriRegistration: false, | ||
grantTypesSupported: ["authorization_code"], | ||
frontchannelLogoutSupported: false, | ||
frontchannelLogoutSessionSupported: false, | ||
backchannelLogoutSupported: false, | ||
backchannelLogoutSessionSupported: false, | ||
issuer: "https://provider.rdobeheer.nl", | ||
authorizationEndpoint: "https://provider.rdobeheer.nl/authorize", | ||
jwksUri: "https://provider.rdobeheer.nl/jwks", | ||
tokenEndpoint: "https://provider.rdobeheer.nl/token", | ||
scopesSupported: ["openid"], | ||
responseTypesSupported: ["code"], | ||
responseModesSupported: ["query"], | ||
subjectTypesSupported: ["pairwise"], | ||
idTokenSigningAlgValuesSupported: ["RS256"], | ||
userinfoEndpoint: "https://provider.rdobeheer.nl/userinfo", | ||
codeChallengeMethodsSupported: ["S256"], | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace MinVWS\OpenIDConnectLaravel\Tests\Unit\Http\Controllers; | ||
|
||
use Exception; | ||
use Illuminate\Contracts\Support\Responsable; | ||
use Illuminate\Http\Request; | ||
use Jumbojett\OpenIDConnectClientException; | ||
use MinVWS\OpenIDConnectLaravel\Http\Controllers\LoginController; | ||
use MinVWS\OpenIDConnectLaravel\Http\Responses\LoginResponse; | ||
use MinVWS\OpenIDConnectLaravel\Http\Responses\LoginResponseInterface; | ||
use MinVWS\OpenIDConnectLaravel\OpenIDConnectClient; | ||
use MinVWS\OpenIDConnectLaravel\Services\JWE\JweDecryptException; | ||
use MinVWS\OpenIDConnectLaravel\Services\OpenIDConnectExceptionHandler; | ||
use Mockery; | ||
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
class LoginControllerTest extends TestCase | ||
{ | ||
use MockeryPHPUnitIntegration; | ||
|
||
protected function setUp(): void | ||
{ | ||
parent::setUp(); | ||
|
||
// Bind the LoginResponseInterface to the LoginResponse class | ||
app()->bind(LoginResponseInterface::class, LoginResponse::class); | ||
} | ||
|
||
protected function tearDown(): void | ||
{ | ||
// Flush so the LoginResponseInterface binding is removed | ||
app()->flush(); | ||
|
||
parent::tearDown(); | ||
} | ||
|
||
public function testLoginControllerCanBeCreated(): void | ||
{ | ||
$loginController = new LoginController( | ||
new OpenIDConnectClient(), | ||
new OpenIDConnectExceptionHandler(), | ||
); | ||
$this->assertInstanceOf(LoginController::class, $loginController); | ||
} | ||
|
||
public function testExceptionHandlerIsCalledWhenAuthenticateThrowsException(): void | ||
{ | ||
$mockClient = Mockery::mock(OpenIDConnectClient::class); | ||
$mockClient | ||
->shouldReceive('authenticate') | ||
->andThrow(OpenIDConnectClientException::class); | ||
|
||
$mockExceptionHandler = Mockery::mock(OpenIDConnectExceptionHandler::class); | ||
$mockExceptionHandler | ||
->shouldReceive('handleExceptionWhileAuthenticate') | ||
->once(); | ||
|
||
$loginController = new LoginController( | ||
$mockClient, | ||
$mockExceptionHandler, | ||
); | ||
|
||
$loginController->__invoke(); | ||
} | ||
|
||
public function testExceptionHandlerIsCalledWhenRequestUserInfoDoesNotReturnAnObject(): void | ||
{ | ||
$mockClient = Mockery::mock(OpenIDConnectClient::class); | ||
$mockClient->shouldReceive('authenticate')->once(); | ||
$mockClient | ||
->shouldReceive('requestUserInfo') | ||
->andReturn('not an object') | ||
->once(); | ||
|
||
$mockExceptionHandler = Mockery::mock(OpenIDConnectExceptionHandler::class); | ||
$mockExceptionHandler | ||
->shouldReceive('handleExceptionWhileRequestUserInfo') | ||
->withArgs(function (OpenIDConnectClientException $e) { | ||
return $e->getMessage() === 'Received user info is not an object'; | ||
}) | ||
->once(); | ||
|
||
$loginController = new LoginController( | ||
$mockClient, | ||
$mockExceptionHandler, | ||
); | ||
|
||
$loginController->__invoke(); | ||
} | ||
|
||
public function testExceptionHandlerIsCalledWhenRequestUserInfoThrowsAnException(): void | ||
{ | ||
$mockClient = Mockery::mock(OpenIDConnectClient::class); | ||
$mockClient->shouldReceive('authenticate')->once(); | ||
$mockClient | ||
->shouldReceive('requestUserInfo') | ||
->andThrow(OpenIDConnectClientException::class, 'Something went wrong') | ||
->once(); | ||
|
||
$mockExceptionHandler = Mockery::mock(OpenIDConnectExceptionHandler::class); | ||
$mockExceptionHandler | ||
->shouldReceive('handleExceptionWhileRequestUserInfo') | ||
->withArgs(function (OpenIDConnectClientException $e) { | ||
return $e->getMessage() === 'Something went wrong'; | ||
}) | ||
->once(); | ||
|
||
$loginController = new LoginController( | ||
$mockClient, | ||
$mockExceptionHandler, | ||
); | ||
|
||
$loginController->__invoke(); | ||
} | ||
|
||
public function testExceptionHandlerIsCalledWhenRequestUserInfoThrowsAnJweDecryptException(): void | ||
{ | ||
$mockClient = Mockery::mock(OpenIDConnectClient::class); | ||
$mockClient->shouldReceive('authenticate')->once(); | ||
$mockClient | ||
->shouldReceive('requestUserInfo') | ||
->andThrow(JweDecryptException::class, 'Something went wrong') | ||
->once(); | ||
|
||
$mockExceptionHandler = Mockery::mock(OpenIDConnectExceptionHandler::class); | ||
$mockExceptionHandler | ||
->shouldReceive('handleException') | ||
->withArgs(function (Exception $e) { | ||
return $e->getMessage() === 'Something went wrong'; | ||
}) | ||
->once(); | ||
|
||
$loginController = new LoginController( | ||
$mockClient, | ||
$mockExceptionHandler, | ||
); | ||
|
||
$loginController->__invoke(); | ||
} | ||
|
||
public function testLoginResponseIsReturnedWithUserInfo(): void | ||
{ | ||
$mockClient = Mockery::mock(OpenIDConnectClient::class); | ||
$mockClient->shouldReceive('authenticate')->once(); | ||
$mockClient | ||
->shouldReceive('requestUserInfo') | ||
->andReturn($this->exampleUserInfo()) | ||
->once(); | ||
|
||
$mockExceptionHandler = Mockery::mock(OpenIDConnectExceptionHandler::class); | ||
|
||
$loginController = new LoginController( | ||
$mockClient, | ||
$mockExceptionHandler, | ||
); | ||
|
||
$response = $loginController->__invoke(); | ||
|
||
$this->assertInstanceOf(LoginResponseInterface::class, $response); | ||
$this->assertInstanceOf(Responsable::class, $response); | ||
} | ||
|
||
public function testUserInfoIsReturned(): void | ||
{ | ||
$mockClient = Mockery::mock(OpenIDConnectClient::class); | ||
$mockClient->shouldReceive('authenticate')->once(); | ||
$mockClient | ||
->shouldReceive('requestUserInfo') | ||
->andReturn($this->exampleUserInfo()) | ||
->once(); | ||
|
||
$mockExceptionHandler = Mockery::mock(OpenIDConnectExceptionHandler::class); | ||
|
||
$loginController = new LoginController( | ||
$mockClient, | ||
$mockExceptionHandler, | ||
); | ||
|
||
$loginResponse = $loginController->__invoke(); | ||
$response = $loginResponse->toResponse(Mockery::mock(Request::class)); | ||
|
||
$this->assertSame(json_encode([ | ||
'userInfo' => $this->exampleUserInfo(), | ||
]), $response->getContent()); | ||
} | ||
|
||
protected function exampleUserInfo(): object | ||
{ | ||
return (object) [ | ||
'sub' => '1234567890', | ||
'name' => 'John Doe', | ||
'given_name' => 'John', | ||
'family_name' => 'Doe', | ||
'middle_name' => 'Middle', | ||
'nickname' => 'JD', | ||
'preferred_username' => 'johndoe', | ||
'email' => '', | ||
]; | ||
} | ||
} |