Skip to content

Commit 3d315ac

Browse files
committed
Convert saml-module to symfony-responses
1 parent e3f18b3 commit 3d315ac

9 files changed

Lines changed: 141 additions & 113 deletions

File tree

modules/saml/src/Auth/Process/ExpectedAuthnContextClassRef.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ protected function unauthorized(array &$state): void
107107
);
108108

109109
$httpUtils = new Utils\HTTP();
110-
$httpUtils->redirectTrustedURL($url, ['StateId' => $id]);
110+
$response = $httpUtils->redirectTrustedURL($url, ['StateId' => $id]);
111+
$response->send();
111112
}
112113
}

modules/saml/src/Auth/Source/SP.php

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ class SP extends Auth\Source
8888
*/
8989
private bool $requestInitiation;
9090

91+
/**
92+
* The global configuration.
93+
*
94+
* @var \SimpleSAML\Configuration
95+
*/
96+
private Configuration $config;
97+
9198

9299
/**
93100
* Constructor for SAML SP authentication source.
@@ -126,6 +133,7 @@ public function __construct(array $info, array $config)
126133
'Please set a valid and unique SP entityID',
127134
);
128135

136+
$this->config = Configuration::getInstance();
129137
$this->entityId = $entityId;
130138
$this->idp = $this->metadata->getOptionalString('idp', null);
131139
$this->discoURL = $this->metadata->getOptionalString('discoURL', null);
@@ -232,12 +240,11 @@ public function getHostedMetadata(): array
232240
}
233241

234242
// add technical contact
235-
$globalConfig = Configuration::getInstance();
236-
$email = $globalConfig->getOptionalString('technicalcontact_email', 'na@example.org');
243+
$email = $this->config->getOptionalString('technicalcontact_email', 'na@example.org');
237244
if (!empty($email) && $email !== 'na@example.org') {
238245
$contact = [
239246
'emailAddress' => $email,
240-
'givenName' => $globalConfig->getOptionalString('technicalcontact_name', null),
247+
'givenName' => $this->config->getOptionalString('technicalcontact_name', null),
241248
'contactType' => 'technical',
242249
];
243250
$metadata['contacts'][] = Utils\Config\Metadata::getContact($contact);
@@ -320,17 +327,18 @@ public function getHostedMetadata(): array
320327
/**
321328
* Retrieve the metadata of an IdP.
322329
*
330+
* @param \SimpleSAML\Configuration $config The configuration
323331
* @param string $entityId The entity id of the IdP.
324332
* @return \SimpleSAML\Configuration The metadata of the IdP.
325333
*/
326-
public function getIdPMetadata(string $entityId): Configuration
334+
public function getIdPMetadata(Configuration $config, string $entityId): Configuration
327335
{
328336
if ($this->idp !== null && $this->idp !== $entityId) {
329337
throw new Error\Exception('Cannot retrieve metadata for IdP ' .
330338
var_export($entityId, true) . ' because it isn\'t a valid IdP for this SP.');
331339
}
332340

333-
$metadataHandler = MetaDataStorageHandler::getMetadataHandler();
341+
$metadataHandler = MetaDataStorageHandler::getMetadataHandler($config);
334342

335343
return $metadataHandler->getMetaDataConfig($entityId, 'saml20-idp-remote');
336344
}
@@ -423,8 +431,7 @@ private function getACSEndpoints(): array
423431
*/
424432
private function getSLOEndpoints(): array
425433
{
426-
$config = Configuration::getInstance();
427-
$storeType = $config->getOptionalString('store.type', 'phpsession');
434+
$storeType = $this->config->getOptionalString('store.type', 'phpsession');
428435

429436
$store = StoreFactory::getInstance($storeType);
430437
$bindings = $this->metadata->getOptionalArray(
@@ -726,12 +733,13 @@ public function sendSAML2LogoutRequest(Binding $binding, LogoutRequest $lr): nev
726733
/**
727734
* Send a SSO request to an IdP.
728735
*
736+
* @param \SimpleSAML\Configuration $config
729737
* @param string $idp The entity ID of the IdP.
730738
* @param array $state The state array for the current authentication.
731739
*/
732-
public function startSSO(string $idp, array $state): never
740+
public function startSSO(Configuration $config, string $idp, array $state): never
733741
{
734-
$idpMetadata = $this->getIdPMetadata($idp);
742+
$idpMetadata = $this->getIdPMetadata($config, $idp);
735743

736744
$type = $idpMetadata->getString('metadata-set');
737745
Assert::oneOf($type, ['saml20-idp-remote']);
@@ -744,8 +752,9 @@ public function startSSO(string $idp, array $state): never
744752
* Start an IdP discovery service operation.
745753
*
746754
* @param array $state The state array.
755+
* @return \Symfony\Component\HttpFoundation\RedirectResponse
747756
*/
748-
private function startDisco(array $state): never
757+
private function startDisco(array $state): RedirectResponse
749758
{
750759
$id = Auth\State::saveState($state, 'saml:sp:sso');
751760

@@ -772,7 +781,7 @@ private function startDisco(array $state): never
772781
}
773782

774783
$httpUtils = new Utils\HTTP();
775-
$httpUtils->redirectTrustedURL($discoURL, $params);
784+
return $httpUtils->redirectTrustedURL($discoURL, $params);
776785
}
777786

778787

@@ -781,9 +790,10 @@ private function startDisco(array $state): never
781790
*
782791
* This function saves the information about the login, and redirects to the IdP.
783792
*
793+
* @param \Symfony\Component\HttpFoundation\Request The current request
784794
* @param array &$state Information about the current authentication.
785795
*/
786-
public function authenticate(array &$state): never
796+
public function authenticate(Request $request, array &$state): Response
787797
{
788798
// We are going to need the authId in order to retrieve this authentication source later
789799
$state['saml:sp:AuthId'] = $this->authId;
@@ -796,7 +806,7 @@ public function authenticate(array &$state): never
796806

797807
if (isset($state['saml:IDPList']) && sizeof($state['saml:IDPList']) > 0) {
798808
// we have a SAML IDPList (we are a proxy): filter the list of IdPs available
799-
$mdh = MetaDataStorageHandler::getMetadataHandler();
809+
$mdh = MetaDataStorageHandler::getMetadataHandler($this->config);
800810
$matchedEntities = $mdh->getMetaDataForEntities($state['saml:IDPList'], 'saml20-idp-remote');
801811

802812
if (empty($matchedEntities)) {
@@ -820,10 +830,12 @@ public function authenticate(array &$state): never
820830
}
821831

822832
if ($idp === null) {
823-
$this->startDisco($state);
833+
$response = $this->startDisco($state);
824834
} else {
825-
$this->startSSO($idp, $state);
835+
$response = $this->startSSO($this->config, $idp, $state);
826836
}
837+
838+
return $response;
827839
}
828840

829841

@@ -861,7 +873,7 @@ public function reauthenticate(array &$state): void
861873
* First, check if we recognize any of the IdPs requested.
862874
*/
863875

864-
$mdh = MetaDataStorageHandler::getMetadataHandler();
876+
$mdh = MetaDataStorageHandler::getMetadataHandler($this->config);
865877
$known_idps = $mdh->getList();
866878
$intersection = array_intersect($state['saml:IDPList'], array_keys($known_idps));
867879

@@ -896,9 +908,11 @@ public function reauthenticate(array &$state): void
896908
$state['core:SP'],
897909
));
898910

899-
$state['saml:sp:IdPMetadata'] = $this->getIdPMetadata($state['saml:sp:IdP']);
911+
$state['saml:sp:IdPMetadata'] = $this->getIdPMetadata($this->config, $state['saml:sp:IdP']);
900912
$state['saml:sp:AuthId'] = $this->authId;
901-
self::askForIdPChange($state);
913+
914+
$response = self::askForIdPChange($state);
915+
return $response;
902916
}
903917

904918
/*
@@ -943,10 +957,11 @@ public function reauthenticate(array &$state): void
943957
* - 'saml:sp:AuthId': the identifier of the current authentication source.
944958
* - 'core:IdP': the identifier of the local IdP.
945959
* - 'SPMetadata': an array with the metadata of this local SP.
960+
* @return \Symfony\Component\HttpFoundation\RedirectResponse
946961
*
947962
* @throws \SAML2\Exception\Protocol\NoPassiveException In case the authentication request was passive.
948963
*/
949-
public static function askForIdPChange(array &$state): never
964+
public static function askForIdPChange(array &$state): RedirectResponse
950965
{
951966
Assert::keyExists($state, 'saml:sp:IdPMetadata');
952967
Assert::keyExists($state, 'saml:sp:AuthId');
@@ -965,7 +980,7 @@ public static function askForIdPChange(array &$state): never
965980
$url = Module::getModuleURL('saml/proxy/invalidSession');
966981

967982
$httpUtils = new Utils\HTTP();
968-
$httpUtils->redirectTrustedURL($url, ['AuthState' => $id]);
983+
return $httpUtils->redirectTrustedURL($url, ['AuthState' => $id]);
969984
}
970985

971986

@@ -1006,7 +1021,7 @@ public static function tryStepUpAuth(array &$state): never
10061021
*
10071022
* @param array $state The state array.
10081023
*/
1009-
public static function reauthLogout(array $state): never
1024+
public static function reauthLogout(Configuration $config, array $state): never
10101025
{
10111026
Logger::debug('Proxy: logging the user out before re-authentication.');
10121027

@@ -1024,8 +1039,9 @@ public static function reauthLogout(array $state): never
10241039
* Complete login operation after re-authenticating the user on another IdP.
10251040
*
10261041
* @param array $state The authentication state.
1042+
* @return \Symfony\Component\HttpFoundation\Response
10271043
*/
1028-
public static function reauthPostLogin(array $state): never
1044+
public static function reauthPostLogin(array $state): Response
10291045
{
10301046
Assert::keyExists($state, 'ReturnCallback');
10311047

@@ -1035,7 +1051,7 @@ public static function reauthPostLogin(array $state): never
10351051
$session->doLogin($authId, Auth\State::getPersistentAuthData($state));
10361052

10371053
// resume the login process
1038-
call_user_func($state['ReturnCallback'], $state);
1054+
return call_user_func($state['ReturnCallback'], $state);
10391055
}
10401056

10411057

@@ -1046,8 +1062,9 @@ public static function reauthPostLogin(array $state): never
10461062
*
10471063
* @param \SimpleSAML\IdP $idp The IdP we are logging out from.
10481064
* @param array &$state The state array with the state during logout.
1065+
* @return \Symfony\Component\HttpFoundation\Response
10491066
*/
1050-
public static function reauthPostLogout(IdP $idp, array $state): never
1067+
public static function reauthPostLogout(IdP $idp, array $state): Response
10511068
{
10521069
Assert::keyExists($state, 'saml:sp:AuthId');
10531070

@@ -1058,19 +1075,21 @@ public static function reauthPostLogout(IdP $idp, array $state): never
10581075
}
10591076

10601077
/** @var \SimpleSAML\Module\saml\Auth\Source\SP $sp */
1061-
$sp = Auth\Source::getById($state['saml:sp:AuthId'], Module\saml\Auth\Source\SP::class);
1078+
$sp = Auth\Source::getById($state['saml:sp:AuthId'], static::class);
10621079

10631080
Logger::debug('Proxy: logging in again.');
1064-
$sp->authenticate($state);
1081+
$request = Request::createFromGlobals();
1082+
return $sp->authenticate($request, $state);
10651083
}
10661084

10671085

10681086
/**
10691087
* Start a SAML 2 logout operation.
10701088
*
1089+
* @param \SimpleSAML\Configuration $config The configuration
10711090
* @param array $state The logout state.
10721091
*/
1073-
public function startSLO2(array &$state): void
1092+
public function startSLO2(Configuration $config, array &$state): void
10741093
{
10751094
Assert::keyExists($state, 'saml:logout:IdP');
10761095
Assert::keyExists($state, 'saml:logout:NameID');
@@ -1082,7 +1101,7 @@ public function startSLO2(array &$state): void
10821101
$nameId = $state['saml:logout:NameID'];
10831102
$sessionIndex = $state['saml:logout:SessionIndex'];
10841103

1085-
$idpMetadata = $this->getIdPMetadata($idp);
1104+
$idpMetadata = $this->getIdPMetadata($config, $idp);
10861105

10871106
/** @var array $endpoint */
10881107
$endpoint = $idpMetadata->getEndpointPrioritizedByBinding(
@@ -1151,13 +1170,14 @@ public function logout(array &$state): void
11511170
* @param array $state The authentication state.
11521171
* @param string $idp The entity id of the IdP.
11531172
* @param array $attributes The attributes.
1173+
* @return \Symfony\Component\HttpFoundation\Response
11541174
*/
1155-
public function handleResponse(array $state, string $idp, array $attributes): never
1175+
public function handleResponse(array $state, string $idp, array $attributes): Response
11561176
{
11571177
Assert::keyExists($state, 'LogoutState');
11581178
Assert::keyExists($state['LogoutState'], 'saml:logout:Type');
11591179

1160-
$idpMetadata = $this->getIdPMetadata($idp);
1180+
$idpMetadata = $this->getIdPMetadata($this->config, $idp);
11611181

11621182
$spMetadataArray = $this->metadata->toArray();
11631183
$idpMetadataArray = $idpMetadata->toArray();
@@ -1187,19 +1207,20 @@ public function handleResponse(array $state, string $idp, array $attributes): ne
11871207
$pc = new Auth\ProcessingChain($idpMetadataArray, $spMetadataArray, 'sp');
11881208
$pc->processState($authProcState);
11891209

1190-
self::onProcessingCompleted($authProcState);
1210+
return self::onProcessingCompleted($authProcState);
11911211
}
11921212

11931213

11941214
/**
11951215
* Handle a logout request from an IdP.
11961216
*
11971217
* @param string $idpEntityId The entity ID of the IdP.
1218+
* @return \Symfony\Component\HttpFoundation\Response
11981219
*/
1199-
public function handleLogout(string $idpEntityId): never
1220+
public function handleLogout(string $idpEntityId): Response
12001221
{
12011222
/* Call the logout callback we registered in onProcessingCompleted(). */
1202-
$this->callLogoutCallback($idpEntityId);
1223+
return $this->callLogoutCallback($idpEntityId);
12031224
}
12041225

12051226

@@ -1223,16 +1244,18 @@ public static function handleUnsolicitedAuth(string $authId, array $state, strin
12231244
$session->doLogin($authId, Auth\State::getPersistentAuthData($state));
12241245

12251246
$httpUtils = new Utils\HTTP();
1226-
$httpUtils->redirectUntrustedURL($redirectTo);
1247+
$response = $httpUtils->redirectUntrustedURL($redirectTo);
1248+
$response->send();
12271249
}
12281250

12291251

12301252
/**
12311253
* Called when we have completed the procssing chain.
12321254
*
12331255
* @param array $authProcState The processing chain state.
1256+
* @return \Symfony\Component\HttpFoundation\Response
12341257
*/
1235-
public static function onProcessingCompleted(array $authProcState): never
1258+
public static function onProcessingCompleted(array $authProcState): Response
12361259
{
12371260
Assert::keyExists($authProcState, 'saml:sp:IdP');
12381261
Assert::keyExists($authProcState, 'saml:sp:State');
@@ -1264,6 +1287,6 @@ public static function onProcessingCompleted(array $authProcState): never
12641287
self::handleUnsolicitedAuth($sourceId, $state, $redirectTo);
12651288
}
12661289

1267-
Auth\Source::completeAuth($state);
1290+
return Auth\Source::completeAuth($state);
12681291
}
12691292
}

modules/saml/src/Controller/Disco.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
namespace SimpleSAML\Module\saml\Controller;
66

77
use SimpleSAML\Configuration;
8-
use SimpleSAML\HTTP\RunnableResponse;
98
use SimpleSAML\XHTML\IdPDisco;
9+
use Symfony\Component\HttpFoundation\Request;
10+
use Symfony\Component\HttpFoundation\Response;
1011

1112
/**
1213
* Controller class for the saml module.
@@ -33,11 +34,12 @@ public function __construct(
3334
/**
3435
* Built-in IdP discovery service
3536
*
36-
* @return \SimpleSAML\HTTP\RunnableResponse
37+
* @param \Symfony\Component\HttpFoundation\Request $request
38+
* @return \Symfony\Component\HttpFoundation\Response
3739
*/
38-
public function disco(): RunnableResponse
40+
public function disco(Request $request): Response
3941
{
40-
$disco = new IdPDisco(['saml20-idp-remote'], 'saml');
41-
return new RunnableResponse([$disco, 'handleRequest']);
42+
$disco = new IdPDisco($request, ['saml20-idp-remote'], 'saml');
43+
return $disco->handleRequest();
4244
}
4345
}

0 commit comments

Comments
 (0)