Skip to content

Commit

Permalink
Support NameId objects in consent hash generator
Browse files Browse the repository at this point in the history
The NameID objects where causing issues when creating a stabilized
consent hash. The objects can not be serialized/unserialized. By
normalizing them before starting to perform other normalization tasks on
the attribute array, this issue can be prevented.
  • Loading branch information
MKodde committed May 4, 2022
1 parent dae614b commit a5dd163
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
27 changes: 24 additions & 3 deletions src/OpenConext/EngineBlock/Service/Consent/ConsentHashService.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
namespace OpenConext\EngineBlock\Service\Consent;

use OpenConext\EngineBlock\Authentication\Repository\ConsentRepository;
use OpenConext\UserLifecycle\Domain\ValueObject\Client\Name;
use SAML2\XML\saml\NameID;
use function array_filter;
use function array_keys;
use function array_values;
Expand All @@ -30,6 +32,7 @@
use function serialize;
use function sha1;
use function sort;
use function str_replace;
use function strtolower;
use function unserialize;

Expand Down Expand Up @@ -90,7 +93,8 @@ public function getUnstableAttributesHash(array $attributes, bool $mustStoreValu

public function getStableAttributesHash(array $attributes, bool $mustStoreValues) : string
{
$lowerCasedAttributes = $this->caseNormalizeStringArray($attributes);
$nameIdNormalizedAttributes = $this->nameIdNormalize($attributes);
$lowerCasedAttributes = $this->caseNormalizeStringArray($nameIdNormalizedAttributes);
$hashBase = $mustStoreValues
? $this->createHashBaseWithValues($lowerCasedAttributes)
: $this->createHashBaseWithoutValues($lowerCasedAttributes);
Expand All @@ -112,11 +116,13 @@ private function createHashBaseWithoutValues(array $lowerCasedAttributes): strin

/**
* Lowercases all array keys and values.
* Performs the lowercasing on a copy (which is returned), to avoid side-effects.
*/
private function caseNormalizeStringArray(array $original): array
{
return unserialize(strtolower(serialize($original)));
$serialized = serialize($original);
$lowerCased = strtolower($serialized);
$unserialized = unserialize($lowerCased);
return $unserialized;
}

/**
Expand Down Expand Up @@ -187,4 +193,19 @@ private function isBlank($value): bool
{
return empty($value) && !is_numeric($value);
}

/**
* NameId objects can not be serialized/unserialized after being lower cased
* Thats why the object is converted to a simple array representation where only the
* relevant NameID aspects are stored.
*/
private function nameIdNormalize(array $attributes): array
{
array_walk_recursive($attributes, function (&$value) {
if ($value instanceof NameID) {
$value = ['value' => $value->getValue(), 'Format' => $value->getFormat()];
}
});
return $attributes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
use OpenConext\EngineBlock\Authentication\Repository\ConsentRepository;
use PHPUnit\Framework\TestCase;
use SAML2\XML\saml\NameID;

class ConsentHashServiceTest extends TestCase
{
Expand Down Expand Up @@ -449,4 +450,28 @@ public function test_stable_attribute_hash_multiple_value_vs_single_value_sequen
$this->assertEquals($this->chs->getStableAttributesHash($attributes, false), $this->chs->getStableAttributesHash($attributesSingleValue, false));
$this->assertNotEquals($this->chs->getStableAttributesHash($attributes, true), $this->chs->getStableAttributesHash($attributesSingleValue, true));
}

public function test_stable_attribute_hash_can_handle_nameid_objects()
{
$nameId = new NameID();
$nameId->setValue('83aa0a79363edcf872c966b0d6eaf3f5e26a6a77');
$nameId->setFormat('urn:oasis:names:tc:SAML:2.0:nameid-format:persistent');

$attributes = [
'urn:mace:dir:attribute-def:displayName' => ['John Doe'],
'urn:mace:dir:attribute-def:uid' => ['joe-f12'],
'urn:mace:dir:attribute-def:cn' => ['John Doe'],
'urn:mace:dir:attribute-def:sn' => ['Doe'],
'urn:mace:dir:attribute-def:eduPersonPrincipalName' => ['j.doe@example.com'],
'urn:mace:dir:attribute-def:givenName' => ['John'],
'urn:mace:dir:attribute-def:mail' => ['j.doe@example.com'],
'urn:mace:terena.org:attribute-def:schacHomeOrganization' => ['example.com'],
'nl:surf:test:something' => [0 => 'arbitrary-value'],
'urn:mace:dir:attribute-def:eduPersonTargetedID' => [$nameId],
'urn:oid:1.3.6.1.4.1.5923.1.1.1.10' => [$nameId],
];

$hash = $this->chs->getStableAttributesHash($attributes, false);
$this->assertTrue(is_string($hash));
}
}

0 comments on commit a5dd163

Please sign in to comment.