Skip to content

Commit

Permalink
Mock calls to one-login endpoints for url generation
Browse files Browse the repository at this point in the history
  • Loading branch information
cooperaj committed Nov 27, 2023
1 parent 2dcd267 commit a206489
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 34 deletions.
1 change: 1 addition & 0 deletions service-api/app/behat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ acceptance:
- BehatTest\Context\Acceptance\CommonContext
- BehatTest\Context\Acceptance\LpaContext
- BehatTest\Context\Acceptance\FeatureFlagContext
- BehatTest\Context\Acceptance\OidcContext
filters:
tags: "@actor&&@acceptance"
viewer:
Expand Down
6 changes: 6 additions & 0 deletions service-api/app/features/bootstrap/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,11 @@
'endpoint' => 'http://iap-images-mock',
],

'one_login' => [
'client_id' => 'client-id',
'discovery_url' => 'http://one-login-mock/.well-known/openid-configuration',
'identity_issuer' => 'http://identity.one-login-mock/',
],

'feature_flags' => [],
];
31 changes: 0 additions & 31 deletions service-api/app/features/context/Acceptance/AccountContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -1292,35 +1292,4 @@ public function iShouldBeToldThatABadRequestWasMade(): void
{
$this->ui->assertSession()->statusCodeEquals(StatusCodeInterface::STATUS_BAD_REQUEST);
}

/**
* @Given /^I am on the temporary one login page$/
*/
public function iAmOnTheTemporaryOneLoginPage(): void
{
// Not needed in this context
}

/**
* @When /^I click the one login button$/
*/
public function iClickTheOneLoginButton(): void
{
// Not needed in this context
}

/**
* @Then /^I am redirected to the redirect page$/
*/
public function iAmRedirectedToTheRedirectPage(): void
{
$this->apiGet('/v1/auth/callback', []);

$this->ui->assertSession()->statusCodeEquals(StatusCodeInterface::STATUS_OK);

$response = $this->getResponseAsJson();

Assert::assertEquals('bf9e7e77-f283-49c6-a79c-65d5d309ef77', $response['Id']);
Assert::assertEquals('[email protected]', $response['Email']);
}
}
189 changes: 189 additions & 0 deletions service-api/app/features/context/Acceptance/OidcContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
<?php

declare(strict_types=1);

namespace BehatTest\Context\Acceptance;

use Aws\Command;
use Aws\Result;
use Aws\ResultInterface;
use Behat\Behat\Context\Context;
use Behat\Behat\Tester\Exception\PendingException;
use Behat\Testwork\Suite\Exception\SuiteSetupException;
use BehatTest\Context\BaseAcceptanceContextTrait;
use BehatTest\Context\SetupEnv;
use Fig\Http\Message\StatusCodeInterface;
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\Assert;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

class OidcContext implements Context
{
use BaseAcceptanceContextTrait;
use SetupEnv;

private ?string $one_login_client_private_key;
private ?string $one_login_client_public_key;

/**
* @beforeScenario @onelogin
*/
public function generateRSAKeyPair()
{
$key = openssl_pkey_new(
[
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
]
);
if ($key === false) {
throw new SuiteSetupException('Unable to create the key', 'onelogin');
}

$details = openssl_pkey_get_details($key);
if (! is_array($details)) {
throw new SuiteSetupException('Unable to get key details', 'onelogin');
}

$success = openssl_pkey_export($key, $this->one_login_client_private_key);
if (!$success) {
throw new SuiteSetupException('Unable to export key to string', 'onelogin');
}

$this->one_login_client_public_key = $details['key'];
}

/**
* @Then /^I am redirected to the one login service$/
*/
public function iAmRedirectedToTheOneLoginService()
{
// AuthorisationClientManager::get()
$this->apiFixtures->append(
function (RequestInterface $request): ResponseInterface {
Assert::assertEquals('/.well-known/openid-configuration', $request->getUri()->getPath());

return new Response(
StatusCodeInterface::STATUS_OK,
[],
json_encode(
[
'authorization_endpoint' => 'https://one-login-mock/authorize',
'issuer' => 'https://one-login-mock',
'token_endpoint' => 'https://one-login-mock/token',
'userinfo_endpoint' => 'https://one-login-mock/userinfo',
'jwks_uri' => 'https://one-login-mock/.well-known/jwks',
],
),
);
},
);

// AbstractKeyPairManager::fetchKeyPairFromSecretsManager()
$this->awsFixtures->append(
function (Command $command): ResultInterface {
Assert::assertEquals('GetSecretValue', $command->getName());
Assert::assertEquals('gov_uk_onelogin_identity_public_key', $command['SecretId']);

return new Result(['SecretString' => $this->one_login_client_public_key]);
}
);

// AbstractKeyPairManager::fetchKeyPairFromSecretsManager()
$this->awsFixtures->append(
function (Command $command): ResultInterface {
Assert::assertEquals('GetSecretValue', $command->getName());
Assert::assertEquals('gov_uk_onelogin_identity_private_key', $command['SecretId']);

return new Result(['SecretString' => $this->one_login_client_private_key]);
}
);

$this->apiGet('/v1/auth/start?redirect_url=http://sut&ui_locale=en');

$this->ui->assertSession()->statusCodeEquals(StatusCodeInterface::STATUS_OK);

$response = $this->getResponseAsJson();

Assert::assertArrayHasKey('state', $response);
Assert::assertArrayHasKey('nonce', $response);
Assert::assertArrayHasKey('url', $response);

Assert::assertIsString($response['state']);
Assert::assertIsString($response['nonce']);

$url = parse_url($response['url']);
Assert::assertSame(
'https://one-login/authorize',
sprintf(
'%s://%s%s',
$url['scheme'],
$url['host'],
$url['path'],
)
);

parse_str($url['query'], $query);
Assert::assertIsString($query['client_id']);
Assert::assertSame('openid email', $query['scope']);
Assert::assertSame('code', $query['response_type']);
Assert::assertSame('http://sut', $query['redirect_uri']);
Assert::assertSame($response['state'], $query['state']);
Assert::assertSame($response['nonce'], $query['nonce']);
Assert::assertSame('["Cl.Cm.P2"]', $query['vtr']);
Assert::assertSame('en', $query['ui_locales']);
Assert::assertSame(
'{"userinfo":{"https://vocab.account.gov.uk/v1/coreIdentityJWT":null}}',
$query['claims']
);
}

/**
* @When /^I am returned to the use an lpa service$/
*/
public function iAmReturnedToTheUseAnLpaService(): void
{
// Not needed in this context
}

/**
* @Then /^I am taken to my dashboard$/
*/
public function iAmTakenToMyDashboard(): void
{
// Not needed in this context
}

/**
* @Given /^I have an existing local account$/
*/
public function iHaveAnExistingLocalAccount(): void
{
throw new PendingException();
}

/**
* @Given /^I have completed a successful one login sign\-in process$/
*/
public function iHaveCompletedASuccessfulOneLoginSignInProcess()
{
throw new PendingException();
}

/**
* @When /^I start the login process$/
*/
public function iStartTheLoginProcess()
{
// Not needed in this context
}

/**
* @Given /^I wish to login to the use an lpa service$/
*/
public function iWishToLoginToTheUseAnLpaService()
{
// Not needed in this context
}
}
13 changes: 10 additions & 3 deletions service-api/app/features/one-login.feature
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ Feature: Authorise One Login

@acceptance
Scenario: I initiate authentication via one login
Given I am on the temporary one login page
When I click the one login button
Then I am redirected to the redirect page
Given I wish to login to the use an lpa service
When I start the login process
Then I am redirected to the one login service

@acceptance @wip
Scenario: I can successfully sign in via one login
Given I have completed a successful one login sign-in process
And I have an existing local account
When I am returned to the use an lpa service
Then I am taken to my dashboard

0 comments on commit a206489

Please sign in to comment.