Skip to content

Commit d265ec8

Browse files
johanibkayjoosten
authored andcommitted
Cover additional flows and add correlation id on the feedback page
1 parent b6f86d5 commit d265ec8

10 files changed

Lines changed: 154 additions & 12 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/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
}

library/EngineBlock/Corto/ProxyServer.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -556,15 +556,12 @@ public function sendStepupAuthenticationRequest(
556556

557557

558558
// Link with the original Request
559-
$authnRequestRepository = EngineBlock_ApplicationSingleton::getInstance()
560-
->getDiContainer()
561-
->getAuthnRequestSessionRepository();
559+
$diContainer = EngineBlock_ApplicationSingleton::getInstance()->getDiContainer();
560+
$authnRequestRepository = $diContainer->getAuthnRequestSessionRepository();
562561
$authnRequestRepository->store($spRequest);
563562
$authnRequestRepository->link($ebRequest, $spRequest);
564563

565-
$correlationIdService = EngineBlock_ApplicationSingleton::getInstance()
566-
->getDiContainer()
567-
->getCorrelationIdService();
564+
$correlationIdService = $diContainer->getCorrelationIdService();
568565
$correlationIdService->mint($spRequest->getId());
569566
$correlationIdService->link($ebRequest->getId(), $spRequest->getId());
570567
$correlationIdService->resolve($spRequest->getId());

src/OpenConext/EngineBlockBundle/Controller/FeedbackController.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
namespace OpenConext\EngineBlockBundle\Controller;
2020

21+
use OpenConext\EngineBlock\Request\CurrentCorrelationId;
2122
use OpenConext\EngineBlock\Service\FeedbackStateHelperInterface;
2223
use OpenConext\EngineBlockBundle\Pdp\PolicyDecision;
2324
use Symfony\Component\HttpFoundation\Request;
@@ -39,14 +40,18 @@ class FeedbackController
3940

4041
private FeedbackStateHelperInterface $feedbackStateHelper;
4142

43+
private CurrentCorrelationId $currentCorrelationId;
44+
4245
public function __construct(
4346
TranslatorInterface $translator,
4447
Environment $twig,
45-
FeedbackStateHelperInterface $feedbackStateHelper
48+
FeedbackStateHelperInterface $feedbackStateHelper,
49+
CurrentCorrelationId $currentCorrelationId
4650
) {
4751
$this->translator = $translator;
4852
$this->twig = $twig;
4953
$this->feedbackStateHelper = $feedbackStateHelper;
54+
$this->currentCorrelationId = $currentCorrelationId;
5055
}
5156

5257
#[Route(
@@ -518,6 +523,9 @@ public function stepupCalloutUnmetLoaAction(Request $request)
518523

519524
private function setFeedbackInformationOnSession(array $customFeedbackInfo): void
520525
{
526+
if ($this->currentCorrelationId->correlationId !== null) {
527+
$customFeedbackInfo['correlationId'] = $this->currentCorrelationId->correlationId;
528+
}
521529
$this->feedbackStateHelper->mergeFeedbackInfo($customFeedbackInfo);
522530
}
523531
}

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)