Skip to content

Commit b60fac7

Browse files
mrvanesjohanib
authored andcommitted
Add SRAM Testfilter
Add processSRAMInterrupt route Working SRAM interrupt route Manipulate attributes in interrupt Add token parameter Rename endpoints
1 parent 6cca5e5 commit b60fac7

File tree

18 files changed

+506
-5
lines changed

18 files changed

+506
-5
lines changed

app/config/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ open_conext_engine_block:
2929
eb.enable_sso_session_cookie: "%feature_enable_sso_session_cookie%"
3030
eb.feature_enable_idp_initiated_flow: "%feature_enable_idp_initiated_flow%"
3131
eb.stepup.sfo.override_engine_entityid: "%feature_stepup_sfo_override_engine_entityid%"
32-
32+
eb.feature_enable_sram_interrupt: "%feature_enable_sram_interrupt%"
3333

3434
swiftmailer:
3535
transport: "%mailer_transport%"

app/config/parameters.yml.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ parameters:
231231
feature_enable_consent: true
232232
feature_stepup_sfo_override_engine_entityid: false
233233
feature_enable_idp_initiated_flow: true
234+
feature_enable_sram_interrupt: true
234235

235236
##########################################################################################
236237
## PROFILE SETTINGS

library/EngineBlock/Application/DiContainer.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,12 @@ protected function getStepupEndpoint()
538538
return $this->container->get('engineblock.configuration.stepup.endpoint');
539539
}
540540

541+
/** @return \OpenConext\EngineBlock\SRAM\SRAMEndpoint $sramEndpoint */
542+
public function getSRAMEndpoint()
543+
{
544+
return $this->container->get('engineblock.configuration.sram.endpoint');
545+
}
546+
541547
/** @return string */
542548
public function getStepupEntityIdOverrideValue()
543549
{

library/EngineBlock/Corto/Adapter.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ public function processWayf()
127127
$this->_callCortoServiceUri('continueToIdp');
128128
}
129129

130+
public function processSRAMInterrupt()
131+
{
132+
$this->_callCortoServiceUri('SRAMInterruptService');
133+
}
134+
130135
public function processConsent()
131136
{
132137
$this->_callCortoServiceUri('processConsentService');
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
/**
4+
* Copyright 2021 Stichting Kennisnet
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+
class EngineBlock_Corto_Filter_Command_SRAMTestFilter extends EngineBlock_Corto_Filter_Command_Abstract
20+
implements EngineBlock_Corto_Filter_Command_ResponseAttributesModificationInterface
21+
{
22+
/**
23+
* {@inheritdoc}
24+
*/
25+
public function getResponseAttributes()
26+
{
27+
return $this->_responseAttributes;
28+
}
29+
30+
public function execute(): void
31+
{
32+
33+
$application = EngineBlock_ApplicationSingleton::getInstance();
34+
35+
$sramEndpoint = $application->getDiContainer()->getSRAMEndpoint();
36+
$sramApiToken = $sramEndpoint->getApiToken();
37+
$sramAuthzLocation = $sramEndpoint->getAuthzLocation();
38+
// $sramAuthzLocation = 'http://192.168.0.1:12345/api';
39+
40+
error_log("SRAMTestFilter execute");
41+
42+
$attributes = $this->getResponseAttributes();
43+
44+
$uid = $attributes['urn:mace:dir:attribute-def:uid'][0];
45+
$id = $this->_request->getId();
46+
$continue_url = $this->_server->getUrl('SRAMInterruptService', '') . "?ID=$id";
47+
48+
$headers = array(
49+
"Authorization: $sramApiToken"
50+
);
51+
52+
$post = array(
53+
'uid' => $uid,
54+
'continue_url' => $continue_url,
55+
);
56+
57+
$options = [
58+
CURLOPT_HEADER => false,
59+
CURLOPT_RETURNTRANSFER => true,
60+
CURLOPT_HTTPHEADER => $headers,
61+
CURLOPT_POST => true,
62+
CURLOPT_POSTFIELDS => $post,
63+
];
64+
65+
66+
$ch = curl_init($sramAuthzLocation);
67+
curl_setopt_array($ch, $options);
68+
69+
$data = curl_exec($ch);
70+
curl_close($ch);
71+
72+
$body = json_decode($data);
73+
error_log("SRAMTestFilter " . var_export($body, true));
74+
75+
$msg = $body->msg;
76+
if ('interrupt' == $msg) {
77+
$this->_response->setSRAMInterruptNonce($body->nonce);
78+
}
79+
80+
}
81+
}

library/EngineBlock/Corto/Filter/Input.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,15 @@ public function getCommands()
9595

9696
// Apply the Attribute Release Policy before we do consent.
9797
new EngineBlock_Corto_Filter_Command_AttributeReleasePolicy(),
98+
9899
);
99100

101+
// SRAM Test filter
102+
// When feature_enable_sram_interrupt enabled
103+
if ($featureConfiguration->isEnabled('eb.feature_enable_sram_interrupt')) {
104+
$commands[] = new EngineBlock_Corto_Filter_Command_SRAMTestFilter();
105+
}
106+
100107
if (!$featureConfiguration->isEnabled('eb.run_all_manipulations_prior_to_consent')) {
101108
return $commands;
102109
}

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,21 @@ public function serve($serviceName, Request $httpRequest)
170170

171171
$this->_server->filterInputAssertionAttributes($receivedResponse, $receivedRequest);
172172

173+
// Send SRAM Interrupt call
174+
if ($receivedResponse->getSRAMInterruptNonce() != Null) {
175+
$log->info('Handle SRAM Interrupt callout');
176+
177+
// Add the SRAM step
178+
$currentProcessStep = $this->_processingStateHelper->addStep(
179+
$receivedRequest->getId(),
180+
ProcessingStateHelperInterface::STEP_SRAM,
181+
$this->getEngineSpRole($this->_server),
182+
$receivedResponse
183+
);
184+
185+
$this->_server->sendSRAMInterruptRequest($receivedResponse, $receivedRequest);
186+
}
187+
173188
// Add the consent step
174189
$currentProcessStep = $this->_processingStateHelper->addStep(
175190
$receivedRequest->getId(),
@@ -214,7 +229,8 @@ public function serve($serviceName, Request $httpRequest)
214229
$nameId,
215230
$sp->getCoins()->isStepupForceAuthn()
216231
);
217-
}
232+
233+
}
218234

219235
/**
220236
* @return AuthenticationState
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
<?php
2+
3+
/**
4+
* Copyright 2010 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+
use OpenConext\EngineBlock\Service\AuthenticationStateHelperInterface;
20+
use OpenConext\EngineBlock\Service\ProcessingStateHelperInterface;
21+
use OpenConext\EngineBlock\Stepup\StepupGatewayCallOutHelper;
22+
use SAML2\Constants;
23+
use SAML2\Response;
24+
use Symfony\Component\HttpFoundation\Request;
25+
26+
class EngineBlock_Corto_Module_Service_SRAMInterrupt
27+
implements EngineBlock_Corto_Module_Service_ServiceInterface
28+
{
29+
/**
30+
* @var EngineBlock_Corto_ProxyServer
31+
*/
32+
protected $_server;
33+
34+
/**
35+
* @var AuthenticationStateHelperInterface
36+
*/
37+
private $_authenticationStateHelper;
38+
39+
/**
40+
* @var ProcessingStateHelperInterface
41+
*/
42+
private $_processingStateHelper;
43+
44+
/**
45+
* @var StepupGatewayCallOutHelper
46+
*/
47+
private $_stepupGatewayCallOutHelper;
48+
49+
50+
public function __construct(
51+
EngineBlock_Corto_ProxyServer $server,
52+
AuthenticationStateHelperInterface $stateHelper,
53+
ProcessingStateHelperInterface $processingStateHelper,
54+
StepupGatewayCallOutHelper $stepupGatewayCallOutHelper
55+
)
56+
{
57+
$this->_server = $server;
58+
$this->_authenticationStateHelper = $stateHelper;
59+
$this->_processingStateHelper = $processingStateHelper;
60+
$this->_stepupGatewayCallOutHelper = $stepupGatewayCallOutHelper;
61+
}
62+
63+
/**
64+
* @param $serviceName
65+
* @param Request $httpRequest
66+
*/
67+
public function serve($serviceName, Request $httpRequest)
68+
{
69+
70+
$application = EngineBlock_ApplicationSingleton::getInstance();
71+
72+
$sramEndpoint = $application->getDiContainer()->getSRAMEndpoint();
73+
$sramApiToken = $sramEndpoint->getApiToken();
74+
$sramEntitlementsLocation = $sramEndpoint->getEntitlementsLocation();
75+
// $sramEntitlementsLocation = 'http://192.168.0.1:12345/entitlements';
76+
77+
$log = $application->getLogInstance();
78+
79+
error_log("EngineBlock_Corto_Module_Service_SRAMInterrupt");
80+
81+
// Get active request
82+
$id = $httpRequest->get('ID');
83+
84+
$nextProcessStep = $this->_processingStateHelper->getStepByRequestId(
85+
$id,
86+
ProcessingStateHelperInterface::STEP_SRAM
87+
);
88+
89+
$receivedResponse = $nextProcessStep->getResponse();
90+
$receivedRequest = $this->_server->getReceivedRequestFromResponse($receivedResponse);
91+
92+
/*
93+
* TODO Add SRAM stuff
94+
* Manipulate attributes
95+
*/
96+
$attributes = $receivedResponse->getAssertion()->getAttributes();
97+
$nonce = $receivedResponse->getSRAMInterruptNonce();
98+
99+
$headers = array(
100+
"Authorization: $sramApiToken"
101+
);
102+
103+
$post = array(
104+
'nonce' => $nonce
105+
);
106+
107+
$options = [
108+
CURLOPT_HEADER => false,
109+
CURLOPT_RETURNTRANSFER => true,
110+
CURLOPT_HTTPHEADER => $headers,
111+
CURLOPT_POST => true,
112+
CURLOPT_POSTFIELDS => $post,
113+
];
114+
115+
116+
$ch = curl_init($sramEntitlementsLocation);
117+
curl_setopt_array($ch, $options);
118+
119+
$data = curl_exec($ch);
120+
curl_close($ch);
121+
122+
$body = json_decode($data);
123+
$entitlements = $body->entitlements;
124+
125+
126+
if ($entitlements) {
127+
$attributes['eduPersonEntitlement'] = $entitlements;
128+
$receivedResponse->getAssertion()->setAttributes($attributes);
129+
}
130+
131+
/*
132+
* Continue to Consent/StepUp
133+
*/
134+
135+
// Flush log if SP or IdP has additional logging enabled
136+
$issuer = $receivedResponse->getIssuer() ? $receivedResponse->getIssuer()->getValue() : '';
137+
$idp = $this->_server->getRepository()->fetchIdentityProviderByEntityId($issuer);
138+
139+
if ($receivedRequest->isDebugRequest()) {
140+
$sp = $this->_server->getEngineSpRole($this->_server);
141+
} else {
142+
$issuer = $receivedRequest->getIssuer() ? $receivedRequest->getIssuer()->getValue() : '';
143+
$sp = $this->_server->getRepository()->fetchServiceProviderByEntityId($issuer);
144+
}
145+
146+
// When dealing with an SP that acts as a trusted proxy, we should use the proxying SP and not the proxy itself.
147+
if ($sp->getCoins()->isTrustedProxy()) {
148+
// Overwrite the trusted proxy SP instance with that of the SP that uses the trusted proxy.
149+
$sp = $this->_server->findOriginalServiceProvider($receivedRequest, $log);
150+
}
151+
152+
$pdpLoas = $receivedResponse->getPdpRequestedLoas();
153+
$loaRepository = $application->getDiContainer()->getLoaRepository();
154+
$authnRequestLoas = $receivedRequest->getStepupObligations($loaRepository->getStepUpLoas());
155+
156+
$shouldUseStepup = $this->_stepupGatewayCallOutHelper->shouldUseStepup($idp, $sp, $authnRequestLoas, $pdpLoas);
157+
158+
// Goto consent if no Stepup authentication is needed
159+
if (!$shouldUseStepup) {
160+
$this->_server->sendConsentAuthenticationRequest($receivedResponse, $receivedRequest, $nextProcessStep->getRole(), $this->_authenticationStateHelper->getAuthenticationState());
161+
return;
162+
}
163+
164+
$log->info('Handle Stepup authentication callout');
165+
166+
// Add Stepup authentication step
167+
$currentProcessStep = $this->_processingStateHelper->addStep(
168+
$receivedRequest->getId(),
169+
ProcessingStateHelperInterface::STEP_STEPUP,
170+
$application->getDiContainer()->getStepupIdentityProvider($this->_server),
171+
$receivedResponse
172+
);
173+
174+
// Get mapped AuthnClassRef and get NameId
175+
$nameId = clone $receivedResponse->getNameId();
176+
$authnClassRef = $this->_stepupGatewayCallOutHelper->getStepupLoa($idp, $sp, $authnRequestLoas, $pdpLoas);
177+
178+
179+
180+
$this->_server->sendStepupAuthenticationRequest(
181+
$receivedRequest,
182+
$currentProcessStep->getRole(),
183+
$authnClassRef,
184+
$nameId,
185+
$sp->getCoins()->isStepupForceAuthn()
186+
);
187+
188+
189+
}
190+
}

library/EngineBlock/Corto/Module/Services.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ private function factoryService($className, EngineBlock_Corto_ProxyServer $serve
113113
$diContainer->getAuthenticationStateHelper(),
114114
$diContainer->getProcessingStateHelper()
115115
);
116+
case EngineBlock_Corto_Module_Service_SRAMInterrupt::class :
117+
return new EngineBlock_Corto_Module_Service_SRAMInterrupt(
118+
$server,
119+
$diContainer->getAuthenticationStateHelper(),
120+
$diContainer->getProcessingStateHelper(),
121+
$diContainer->getStepupGatewayCallOutHelper()
122+
);
116123
case EngineBlock_Corto_Module_Service_AssertionConsumer::class :
117124
return new EngineBlock_Corto_Module_Service_AssertionConsumer(
118125
$server,

0 commit comments

Comments
 (0)