-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Overwrite the NameID when specified in use_as_nameid ARP setting #1308
Changes from all commits
b82468c
fe47992
da3ea77
b6f59b0
884aa27
2acb8c9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
use OpenConext\EngineBlock\Metadata\AttributeReleasePolicy; | ||
use Psr\Log\LoggerInterface; | ||
|
||
/** | ||
* Copyright 2024 SURFnet B.V. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
class EngineBlock_Arp_NameIdSubstituteResolver | ||
{ | ||
/** | ||
* @var LoggerInterface | ||
*/ | ||
private $logger; | ||
|
||
public function __construct(LoggerInterface $logger) | ||
{ | ||
$this->logger = $logger; | ||
} | ||
|
||
public function findNameIdSubstitute(AttributeReleasePolicy $arp, array $responseAttributes): ?string | ||
{ | ||
$substituteAttribute = $arp->findNameIdSubstitute(); | ||
if ($substituteAttribute !== null && array_key_exists($substituteAttribute, $responseAttributes)) { | ||
$this->logger->notice( | ||
sprintf( | ||
'Found a NameId substitute ("use_as_nameid", %s will be used as NameID)', | ||
$substituteAttribute | ||
) | ||
); | ||
return reset($responseAttributes[$substituteAttribute]); | ||
} | ||
return null; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,8 +16,10 @@ | |
* limitations under the License. | ||
*/ | ||
|
||
use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider; | ||
use Psr\Log\LoggerInterface; | ||
use SAML2\Constants; | ||
use SAML2\XML\saml\NameID; | ||
|
||
class EngineBlock_Corto_Filter_Command_AddIdentityAttributes extends EngineBlock_Corto_Filter_Command_Abstract | ||
implements EngineBlock_Corto_Filter_Command_ResponseAttributesModificationInterface | ||
|
@@ -27,8 +29,23 @@ class EngineBlock_Corto_Filter_Command_AddIdentityAttributes extends EngineBlock | |
*/ | ||
private $logger; | ||
|
||
public function __construct(LoggerInterface $logger) | ||
{ | ||
/** | ||
* @var EngineBlock_Saml2_NameIdResolver | ||
*/ | ||
private $nameIdResolver; | ||
|
||
/** | ||
* @var EngineBlock_Arp_NameIdSubstituteResolver | ||
*/ | ||
private $substituteResolver; | ||
|
||
public function __construct( | ||
EngineBlock_Saml2_NameIdResolver $nameIdResolver, | ||
EngineBlock_Arp_NameIdSubstituteResolver $resolver, | ||
LoggerInterface $logger | ||
) { | ||
$this->nameIdResolver = $nameIdResolver; | ||
$this->substituteResolver = $resolver; | ||
$this->logger = $logger; | ||
} | ||
|
||
|
@@ -54,28 +71,56 @@ public function execute() | |
$this->_server->getRepository() | ||
); | ||
|
||
// Resolve what NameID we should send the destination. | ||
$resolver = new EngineBlock_Saml2_NameIdResolver($this->logger); | ||
$nameId = $resolver->resolve( | ||
$this->_request, | ||
$this->_response, | ||
$destinationMetadata, | ||
$this->_collabPersonId | ||
); | ||
$isResolved = false; | ||
|
||
$this->logger->info('Setting the NameId on the Assertion'); | ||
$this->_response->getAssertion()->setNameId($nameId); | ||
$arp = $destinationMetadata->getAttributeReleasePolicy(); | ||
if (!is_null($arp)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we go through the trouble to resolve a nameid above if we're going to overwrite it anyway? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I looked at it like this:
What could be done is to move the NameIdResolver logic down below, and only resolve the nameId if we did not use the substitute. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright, there's two ways to look at this, you do what you think is best |
||
// Now check if we should update the NameID value according to the 'use_as_nameid' directive in the ARP. | ||
$arpSubstitute = $this->substituteResolver->findNameIdSubstitute($arp, $this->getResponseAttributes()); | ||
if ($arpSubstitute !== null) { | ||
$nameId = new NameID(); | ||
$nameId->setFormat(Constants::NAMEID_UNSPECIFIED); | ||
$nameId->setValue($arpSubstitute); | ||
$isResolved = true; | ||
$this->_response->getAssertion()->setNameId($nameId); | ||
} | ||
|
||
// If there's an ARP, but it does not contain the EPTI, we're done now. | ||
if (!$arp->hasAttribute(Constants::EPTI_URN_MACE)) { | ||
return; | ||
} | ||
} | ||
|
||
if (!$isResolved || !isset($nameId)){ | ||
// Resolve what NameID we should send the destination. | ||
$resolver = new EngineBlock_Saml2_NameIdResolver($this->logger); | ||
$nameId = $resolver->resolve( | ||
$this->_request, | ||
$this->_response, | ||
$destinationMetadata, | ||
$this->_collabPersonId | ||
); | ||
|
||
// Find out if the EduPersonTargetedId is in the ARP of the destination SP. | ||
// If the ARP is NULL this means no ARP = let everything through including ePTI. | ||
// Otherwise only add ePTI if it's acutally in the ARP. | ||
$arp = $destinationMetadata->getAttributeReleasePolicy(); | ||
if (!is_null($arp) && !$arp->hasAttribute(Constants::EPTI_URN_MACE)) { | ||
return; | ||
$this->logger->info('Setting the NameId on the Assertion'); | ||
$this->_response->getAssertion()->setNameId($nameId); | ||
} | ||
|
||
// We arrive here if either: | ||
// 1) the ARP is NULL, this means no ARP = let everything through including EPTI; or | ||
// 2) the ARP is not null and does contain the EPTI attribute. | ||
// In both cases, set the EPTI attribute. | ||
$this->logger->info('Adding the EduPersonTargetedId on the Assertion'); | ||
$this->_responseAttributes[Constants::EPTI_URN_MACE] = [ $nameId ]; | ||
$this->_responseAttributes[Constants::EPTI_URN_MACE] = [$nameId]; | ||
} | ||
|
||
private function resolveNameId(ServiceProvider $destinationMetadata): NameID | ||
{ | ||
// Resolve what NameID we should send the destination. | ||
return $this->nameIdResolver->resolve( | ||
$this->_request, | ||
$this->_response, | ||
$destinationMetadata, | ||
$this->_collabPersonId | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ | |
namespace OpenConext\EngineBlock\Metadata; | ||
|
||
use InvalidArgumentException; | ||
use function array_key_exists; | ||
|
||
class AttributeReleasePolicy | ||
{ | ||
|
@@ -139,6 +140,9 @@ public function findNameIdSubstitute(): ?string | |
foreach ($this->attributeRules as $name => $rules) { | ||
foreach ($rules as $rule) { | ||
if (isset($rule['use_as_nameid']) && $rule['use_as_nameid'] === true) { | ||
if (array_key_exists('release_as', $rule)) { | ||
return $rule['release_as']; | ||
} | ||
Comment on lines
142
to
+145
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this be combined in a local method like ruleHasReleaseAs or so? if ($this->ruleHasReleaseAs($rule)) {
return $rule['release_as'];
} |
||
return $name; | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest to encapsulate this complex if in a descriptive private method like isValidAttibute