Skip to content

Commit 3557fe0

Browse files
committed
Cover additional flows and add correlation id on the feedback page
1 parent d922f40 commit 3557fe0

10 files changed

Lines changed: 156 additions & 6 deletions

File tree

languages/messages.en.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949

5050
// Feedback
5151
'requestId' => 'UR ID',
52+
'correlationId' => 'CID',
5253
'identityProvider' => 'IdP',
5354
'serviceProvider' => 'SP',
5455
'serviceProviderName' => 'SP Name',

languages/messages.nl.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949

5050
// Feedback
5151
'requestId' => 'UR ID',
52+
'correlationId' => 'CID',
5253
'identityProvider' => 'IdP',
5354
'serviceProvider' => 'SP',
5455
'serviceProviderName' => 'SP Name',

library/EngineBlock/Application/DiContainer.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use OpenConext\EngineBlock\Metadata\LoaRepository;
2222
use OpenConext\EngineBlock\Metadata\MetadataRepository\MetadataRepositoryInterface;
2323
use OpenConext\EngineBlock\Request\CorrelationIdService;
24+
use OpenConext\EngineBlock\Request\CurrentCorrelationId;
2425
use OpenConext\EngineBlock\Service\MfaHelperInterface;
2526
use OpenConext\EngineBlock\Service\ReleaseAsEnforcer;
2627
use OpenConext\EngineBlock\Service\TimeProvider\TimeProviderInterface;
@@ -623,6 +624,14 @@ public function getCorrelationIdService(): CorrelationIdService
623624
return $this->container->get(CorrelationIdService::class);
624625
}
625626

627+
/**
628+
* @return CurrentCorrelationId
629+
*/
630+
public function getCurrentCorrelationId(): CurrentCorrelationId
631+
{
632+
return $this->container->get(CurrentCorrelationId::class);
633+
}
634+
626635
/**
627636
* @return EngineBlock_Saml2_AuthnRequestSessionRepository
628637
*/

library/EngineBlock/ApplicationSingleton.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ public function collectFeedbackInfo(Throwable $exception)
269269
$feedbackInfo['ipAddress'] = $this->getClientIpAddress();
270270
$feedbackInfo['artCode'] = Art::forException($exception);
271271

272+
$currentCorrelationId = $this->getDiContainer()->getCurrentCorrelationId()->correlationId;
273+
if ($currentCorrelationId !== null) {
274+
$feedbackInfo['correlationId'] = $currentCorrelationId;
275+
}
276+
272277
// @todo reset this when login is succesful
273278
// Find the current identity provider
274279
$spEntityId = $_SESSION['originalServiceProvider'] ?? $_SESSION['currentServiceProvider'] ?? null;

library/EngineBlock/Corto/Module/Service/SramInterrupt.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ public function serve($serviceName, Request $httpRequest): void
5050
{
5151
$id = $httpRequest->get('ID');
5252

53+
EngineBlock_ApplicationSingleton::getInstance()->getDiContainer()->getCorrelationIdService()->resolve($id);
54+
5355
$nextProcessStep = $this->_processingStateHelper->getStepByRequestId(
5456
$id,
5557
ProcessingStateHelperInterface::STEP_SRAM

library/EngineBlock/Corto/Module/Service/StepupAssertionConsumer.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ public function serve($serviceName, Request $httpRequest)
115115
$log->warning('After failed Stepup authentication set LoA to Loa1', ['result' => $mappedLoa]);
116116
}
117117

118+
$application->getDiContainer()->getCorrelationIdService()->resolve($receivedRequest->getId());
119+
118120
if ($checkResponseSignature) {
119121
$this->_server->checkResponseSignatureMethods($receivedResponse);
120122
}

src/OpenConext/EngineBlockBundle/Controller/FeedbackController.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
namespace OpenConext\EngineBlockBundle\Controller;
2020

2121
use EngineBlock_Corto_ProxyServer;
22+
use OpenConext\EngineBlock\Request\CurrentCorrelationId;
2223
use OpenConext\EngineBlockBundle\Pdp\PolicyDecision;
2324
use Psr\Log\LoggerInterface;
2425
use Symfony\Component\HttpFoundation\Request;
@@ -50,14 +51,18 @@ class FeedbackController
5051
*/
5152
private $logger;
5253

54+
private CurrentCorrelationId $currentCorrelationId;
55+
5356
public function __construct(
5457
TranslatorInterface $translator,
5558
Environment $twig,
56-
LoggerInterface $logger
59+
LoggerInterface $logger,
60+
CurrentCorrelationId $currentCorrelationId
5761
) {
5862
$this->translator = $translator;
5963
$this->twig = $twig;
6064
$this->logger = $logger;
65+
$this->currentCorrelationId = $currentCorrelationId;
6166

6267
// we have to start the old session in order to be able to retrieve the feedback info
6368
$server = new EngineBlock_Corto_ProxyServer($twig);
@@ -545,6 +550,9 @@ public function stepupCalloutUnknownAction(Request $request)
545550
*/
546551
private function setFeedbackInformationOnSession(SessionInterface $session, array $customFeedbackInfo)
547552
{
553+
if ($this->currentCorrelationId->correlationId !== null) {
554+
$customFeedbackInfo['correlationId'] = $this->currentCorrelationId->correlationId;
555+
}
548556
$feedbackInfo = $session->get('feedbackInfo', []);
549557
$session->set('feedbackInfo', array_merge($customFeedbackInfo, $feedbackInfo));
550558
}

src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/LoggingContext.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ public function theLogShouldContainMultipleDistinctRequestIds(): void
9696
{
9797
$records = $this->readRecords();
9898

99-
$requestIds = array_column($records, 'extra')
100-
|> (static fn($x) => array_column($x, 'request_id',))
101-
|> array_unique(...);
102-
99+
$requestIds = array_unique(array_column(
100+
array_column($records, 'extra'),
101+
'request_id',
102+
));
103103
if (count($requestIds) < 2) {
104104
throw new RuntimeException(sprintf(
105105
'Expected multiple distinct request_ids in the log, but found only %d: %s.',

src/OpenConext/EngineBlockFunctionalTestingBundle/Features/CorrelationId.feature

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Feature:
6565
And I give my consent
6666
And I pass through EngineBlock
6767
Then the url should match "functional-testing/CorrId-SP/acs"
68-
And I dump the log records
68+
# And I dump the log records
6969
And the following log messages should have a correlation_id:
7070
| message |
7171
| HTTP-Post: Sending Message |
@@ -102,6 +102,41 @@ Feature:
102102
| Done calling service 'processedAssertionConsumerService' |
103103
| Done calling service 'processConsentService' |
104104

105+
Scenario: A user completing a Stepup flow has a single correlation_id across all log entries
106+
Given the SP "CorrId-SP" requires Stepup LoA "http://dev.openconext.local/assurance/loa2"
107+
And an Identity Provider named "CorrId-IdP"
108+
When I log in at "CorrId-SP"
109+
And I pass through EngineBlock
110+
And I pass through the IdP
111+
And Stepup will successfully verify a user
112+
And I give my consent
113+
And I pass through EngineBlock
114+
Then the url should match "functional-testing/CorrId-SP/acs"
115+
And the log should contain multiple distinct request_ids
116+
And the following log messages should have a correlation_id:
117+
| message |
118+
| Handle Stepup authentication callout |
119+
| Handled Stepup authentication callout successfully |
120+
121+
Scenario: A user completing an SRAM interrupt flow has a single correlation_id across all log entries
122+
Given the SP "CorrId-SP" requires SRAM collaboration
123+
And feature "eb.feature_enable_sram_interrupt" is enabled
124+
And the sbs server will trigger the "interrupt" authz flow when called
125+
And the sbs server will return valid attributes
126+
And an Identity Provider named "CorrId-IdP-SRAM"
127+
When I log in at "CorrId-SP"
128+
And I pass through EngineBlock
129+
And I pass through the IdP
130+
And I pass through SBS
131+
And I give my consent
132+
And I pass through EngineBlock
133+
Then the url should match "functional-testing/CorrId-SP/acs"
134+
And the log should contain multiple distinct request_ids
135+
And the following log messages should have a correlation_id:
136+
| message |
137+
| Handle SRAM interrupt callout |
138+
| Done calling service 'SramInterruptService' |
139+
105140
@functional
106141
Scenario: Two concurrent authentication flows each complete independently
107142
Given an Identity Provider named "CorrId-IdP-A"
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
/**
4+
* Copyright 2026 SURFnet B.V.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
namespace OpenConext\EngineBlockBundle\Tests;
20+
21+
use Mockery;
22+
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
23+
use OpenConext\EngineBlock\Request\CurrentCorrelationId;
24+
use OpenConext\EngineBlockBundle\Controller\FeedbackController;
25+
use PHPUnit\Framework\Attributes\Test;
26+
use PHPUnit\Framework\TestCase;
27+
use Psr\Log\LoggerInterface;
28+
use Symfony\Component\HttpFoundation\Request;
29+
use Symfony\Component\HttpFoundation\Session\Session;
30+
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
31+
use Symfony\Contracts\Translation\TranslatorInterface;
32+
use Twig\Environment;
33+
34+
class FeedbackControllerTest extends TestCase
35+
{
36+
use MockeryPHPUnitIntegration;
37+
38+
#[Test]
39+
public function correlation_id_is_added_to_feedback_session_when_set(): void
40+
{
41+
$currentCorrelationId = new CurrentCorrelationId();
42+
$currentCorrelationId->correlationId = 'test-correlation-id-abc123';
43+
44+
$controller = $this->buildController($currentCorrelationId);
45+
$request = $this->buildRequestWithSession();
46+
47+
$controller->unknownServiceProviderAction($request);
48+
49+
$feedbackInfo = $request->getSession()->get('feedbackInfo');
50+
$this->assertArrayHasKey('correlationId', $feedbackInfo);
51+
$this->assertSame('test-correlation-id-abc123', $feedbackInfo['correlationId']);
52+
}
53+
54+
#[Test]
55+
public function correlation_id_is_not_added_to_feedback_session_when_null(): void
56+
{
57+
$currentCorrelationId = new CurrentCorrelationId();
58+
$currentCorrelationId->correlationId = null;
59+
60+
$controller = $this->buildController($currentCorrelationId);
61+
$request = $this->buildRequestWithSession();
62+
63+
$controller->unknownServiceProviderAction($request);
64+
65+
$feedbackInfo = $request->getSession()->get('feedbackInfo');
66+
$this->assertArrayNotHasKey('correlationId', $feedbackInfo);
67+
}
68+
69+
private function buildController(CurrentCorrelationId $currentCorrelationId): FeedbackController
70+
{
71+
$translator = Mockery::mock(TranslatorInterface::class);
72+
$twig = Mockery::mock(Environment::class);
73+
$twig->allows('render')->andReturn('<html></html>');
74+
$logger = Mockery::mock(LoggerInterface::class);
75+
76+
return new FeedbackController($translator, $twig, $logger, $currentCorrelationId);
77+
}
78+
79+
private function buildRequestWithSession(): Request
80+
{
81+
$request = Request::create('/authentication/feedback/unknown-service-provider?entity-id=https://sp.example.com');
82+
$session = new Session(new MockArraySessionStorage());
83+
$request->setSession($session);
84+
85+
return $request;
86+
}
87+
}

0 commit comments

Comments
 (0)