Skip to content

Commit be9cc74

Browse files
authored
Make sub claim value single value only (#309)
1 parent 0080cf2 commit be9cc74

File tree

2 files changed

+123
-1
lines changed

2 files changed

+123
-1
lines changed

src/Utils/ClaimTranslatorExtractor.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,33 @@ class ClaimTranslatorExtractor
125125
'sub_jwk',
126126
];
127127

128+
/**
129+
* As per https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
130+
*/
131+
final public const MANDATORY_SINGLE_VALUE_CLAIMS = [
132+
'sub',
133+
// TODO mivanci v7 Uncomment the rest of the claims, as this was a potential breaking change in v6.
134+
// 'name',
135+
// 'given_name',
136+
// 'family_name',
137+
// 'middle_name',
138+
// 'nickname',
139+
// 'preferred_username',
140+
// 'profile',
141+
// 'picture',
142+
// 'website',
143+
// 'email',
144+
// 'email_verified',
145+
// 'gender',
146+
// 'birthdate',
147+
// 'zoneinfo',
148+
// 'locale',
149+
// 'phone_number',
150+
// 'phone_number_verified',
151+
// 'address',
152+
// 'updated_at',
153+
];
154+
128155
/**
129156
* ClaimTranslatorExtractor constructor.
130157
*
@@ -248,7 +275,8 @@ private function translateSamlAttributesToClaims(array $translationTable, array
248275
foreach ($attributes as $samlMatch) {
249276
if (array_key_exists($samlMatch, $samlAttributes)) {
250277
/** @psalm-suppress MixedAssignment, MixedArgument */
251-
$values = in_array($claim, $this->allowedMultiValueClaims, true) ?
278+
$values = (!in_array($claim, self::MANDATORY_SINGLE_VALUE_CLAIMS, true)) &&
279+
in_array($claim, $this->allowedMultiValueClaims, true) ?
252280
$samlAttributes[$samlMatch] :
253281
current($samlAttributes[$samlMatch]);
254282
/** @psalm-suppress MixedAssignment */

tests/unit/src/Utils/ClaimTranslatorExtractorTest.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,4 +292,98 @@ public function testCanUnsetClaimWhichIsSupportedByDefault(): void
292292
$translate = ['nickname' => []];
293293
$this->assertFalse(in_array('nickname', $this->mock([], $translate)->getSupportedClaims(), true));
294294
}
295+
296+
public function testCanReleaseMultiValueClaims(): void
297+
{
298+
$claimSet = new ClaimSetEntity(
299+
'multiValueClaimsScope',
300+
['multiValueClaim'],
301+
);
302+
303+
$translate = [
304+
'multiValueClaim' => [
305+
'multiValueAttribute',
306+
],
307+
];
308+
309+
$userAttributes = [
310+
'multiValueAttribute' => ['1', '2', '3'],
311+
];
312+
313+
314+
$claimTranslator = $this->mock([$claimSet], $translate, ['multiValueClaim']);
315+
316+
$releasedClaims = $claimTranslator->extract(
317+
['multiValueClaimsScope'],
318+
$userAttributes,
319+
);
320+
321+
$expectedClaims = [
322+
'multiValueClaim' => ['1', '2', '3'],
323+
];
324+
325+
$this->assertSame($expectedClaims, $releasedClaims);
326+
}
327+
328+
public function testWillReleaseSingleValueClaimsIfMultiValueNotAllowed(): void
329+
{
330+
$claimSet = new ClaimSetEntity(
331+
'multiValueClaimsScope',
332+
['multiValueClaim'],
333+
);
334+
335+
336+
$translate = [
337+
'multiValueClaim' => [
338+
'multiValueAttribute',
339+
],
340+
];
341+
342+
$userAttributes = [
343+
'multiValueAttribute' => ['1', '2', '3'],
344+
];
345+
346+
$claimTranslator = $this->mock([$claimSet], $translate, []);
347+
348+
$releasedClaims = $claimTranslator->extract(
349+
['multiValueClaimsScope'],
350+
$userAttributes,
351+
);
352+
353+
$expectedClaims = ['multiValueClaim' => '1'];
354+
355+
$this->assertSame($expectedClaims, $releasedClaims);
356+
}
357+
358+
public function testWillReleaseSingleValueClaimsForMandatorySingleValueClaims(): void
359+
{
360+
361+
// TODO mivanci v7 Test for mandatory single value claims in other scopes, as per
362+
// \SimpleSAML\Module\oidc\Utils\ClaimTranslatorExtractor::MANDATORY_SINGLE_VALUE_CLAIMS
363+
$claimSet = new ClaimSetEntity(
364+
'customScopeWithSubClaim',
365+
['sub'],
366+
);
367+
368+
$translate = [
369+
'sub' => [
370+
'subAttribute',
371+
],
372+
];
373+
374+
$userAttributes = [
375+
'subAttribute' => ['1', '2', '3'],
376+
];
377+
378+
$claimTranslator = $this->mock([$claimSet], $translate, ['sub']);
379+
380+
$releasedClaims = $claimTranslator->extract(
381+
['openid'],
382+
$userAttributes,
383+
);
384+
385+
$expectedClaims = ['sub' => '1'];
386+
387+
$this->assertSame($expectedClaims, $releasedClaims);
388+
}
295389
}

0 commit comments

Comments
 (0)