Skip to content

Commit 0583369

Browse files
author
Dennis Coorn
committed
Added a SimpleAttributeMapper
* SimpleAttributeMapper added that maps all Attribute values from all Assertions to a single array of attributes * 'lightsaml_sp.attribute_mapper.simple' service added and defined as defaultValue for 'attribute_mapper' in security configuration * SimpleAttributeMapperTest added to guarantee the expected behavior of the mapper
1 parent 4a62c9d commit 0583369

7 files changed

Lines changed: 229 additions & 3 deletions

File tree

src/LightSaml/SpBundle/DependencyInjection/Security/Factory/LightSamlSpFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public function addConfiguration(NodeDefinition $node)
2727
->booleanNode('force')->defaultFalse()->end()
2828
->scalarNode('username_mapper')->defaultValue('lightsaml_sp.username_mapper.simple')->end()
2929
->scalarNode('user_creator')->defaultNull()->end()
30-
->scalarNode('attribute_mapper')->defaultNull()->end()
30+
->scalarNode('attribute_mapper')->defaultValue('lightsaml_sp.attribute_mapper.simple')->end()
3131
->scalarNode('token_factory')->defaultValue('lightsaml_sp.token_factory')->end()
3232
->end()
3333
->end();

src/LightSaml/SpBundle/Resources/config/security.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ services:
1515
- "@security.user_checker"
1616
- "@lightsaml_sp.username_mapper.simple" # username mapper
1717
- ~ # user creator
18-
- ~ # attribute mapper
18+
- "@lightsaml_sp.attribute_mapper.simple" # attribute mapper
1919
- ~ # token factory
2020
abstract: true

src/LightSaml/SpBundle/Resources/config/services.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@ services:
88
arguments:
99
- []
1010

11+
lightsaml_sp.attribute_mapper.simple:
12+
class: LightSaml\SpBundle\Security\User\SimpleAttributeMapper
13+
1114
lightsaml_sp.token_factory:
1215
class: LightSaml\SpBundle\Security\Authentication\Token\SamlSpTokenFactory
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespace LightSaml\SpBundle\Security\User;
4+
5+
use LightSaml\Model\Assertion\Assertion;
6+
use LightSaml\Model\Assertion\Attribute;
7+
use LightSaml\Model\Assertion\AttributeStatement;
8+
use LightSaml\SpBundle\Security\Authentication\Token\SamlSpResponseToken;
9+
10+
class SimpleAttributeMapper implements AttributeMapperInterface
11+
{
12+
/**
13+
* @param SamlSpResponseToken $token
14+
*
15+
* @return array
16+
*/
17+
public function getAttributes(SamlSpResponseToken $token)
18+
{
19+
$response = $token->getResponse();
20+
$assertions = $response->getAllAssertions();
21+
22+
return array_reduce($assertions, [$this, 'resolveAttributesFromAssertion'], []);
23+
}
24+
25+
/**
26+
* @param array $attributes
27+
* @param Assertion $assertion
28+
*
29+
* @return array
30+
*/
31+
private function resolveAttributesFromAssertion(array $attributes, Assertion $assertion)
32+
{
33+
$attributeStatements = $assertion->getAllAttributeStatements();
34+
35+
return array_reduce($attributeStatements, [$this, 'resolveAttributesFromAttributeStatement'], $attributes);
36+
}
37+
38+
/**
39+
* @param array $attributes
40+
* @param AttributeStatement $attributeStatement
41+
*
42+
* @return array
43+
*/
44+
private function resolveAttributesFromAttributeStatement(array $attributes, AttributeStatement $attributeStatement)
45+
{
46+
$statementAttributes = $attributeStatement->getAllAttributes();
47+
48+
return array_reduce($statementAttributes, [$this, 'mapAttributeValues'], $attributes);
49+
}
50+
51+
/**
52+
* @param array $attributes
53+
* @param Attribute $attribute
54+
*
55+
* @return array
56+
*/
57+
private function mapAttributeValues(array $attributes, Attribute $attribute)
58+
{
59+
$key = $attribute->getName();
60+
$value = $attribute->getAllAttributeValues();
61+
62+
if (!array_key_exists($key, $attributes) && count($value) === 1) {
63+
$value = array_shift($value);
64+
}
65+
66+
if (array_key_exists($key, $attributes)) {
67+
$currentValue = (is_array($attributes[$key]) ? $attributes[$key] : [$attributes[$key]]);
68+
69+
$value = array_merge($currentValue, $value);
70+
}
71+
72+
$attributes[$key] = $value;
73+
74+
return $attributes;
75+
}
76+
}

tests/LightSaml/SpBundle/Tests/DependencyInjection/LightSamlSpExtensionTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public function loads_service_provider()
2222
['security.authentication.listener.lightsaml_sp'],
2323
['security.authentication.provider.lightsaml_sp'],
2424
['lightsaml_sp.username_mapper.simple'],
25+
['lightsaml_sp.attribute_mapper.simple'],
2526
['lightsaml_sp.token_factory'],
2627
];
2728
}

tests/LightSaml/SpBundle/Tests/DependencyInjection/Security/Factory/LightSamlSpFactoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function configuration_provider()
3434
['force', BooleanNode::class, false],
3535
['username_mapper', ScalarNode::class, 'lightsaml_sp.username_mapper.simple'],
3636
['user_creator', ScalarNode::class, null],
37-
['attribute_mapper', ScalarNode::class, null],
37+
['attribute_mapper', ScalarNode::class, 'lightsaml_sp.attribute_mapper.simple'],
3838
['token_factory', ScalarNode::class, 'lightsaml_sp.token_factory'],
3939
];
4040
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<?php
2+
3+
namespace LightSaml\SpBundle\Tests\Security\User;
4+
5+
use LightSaml\Model\Assertion\Assertion;
6+
use LightSaml\Model\Assertion\Attribute;
7+
use LightSaml\Model\Assertion\AttributeStatement;
8+
use LightSaml\Model\Protocol\Response;
9+
use LightSaml\SpBundle\Security\Authentication\Token\SamlSpResponseToken;
10+
use LightSaml\SpBundle\Security\User\SimpleAttributeMapper;
11+
12+
class SimpleAttributeMapperTest extends \PHPUnit_Framework_TestCase
13+
{
14+
public function test_get_attributes_from_single_assertion_response()
15+
{
16+
$assertion = $this->buildAssertion([
17+
'organization' => 'test',
18+
'name' => 'John',
19+
'email_address' => 'john@domain.com',
20+
'test' => ['one', 'two'],
21+
]);
22+
$response = $this->buildResponse($assertion);
23+
$samlSpResponseToken = $this->buildSamlSpResponseToken($response);
24+
25+
$expectedAttributes = [
26+
'organization' => 'test',
27+
'name' => 'John',
28+
'email_address' => 'john@domain.com',
29+
'test' => ['one', 'two'],
30+
];
31+
32+
$simpleAttributeMapper = new SimpleAttributeMapper();
33+
$actualAttributes = $simpleAttributeMapper->getAttributes($samlSpResponseToken);
34+
35+
$this->assertEquals($expectedAttributes, $actualAttributes);
36+
}
37+
38+
public function test_get_attributes_from_multi_assertions_response()
39+
{
40+
$assertion = $this->buildAssertion([
41+
'organization' => 'test',
42+
'name' => 'John',
43+
'email_address' => 'john@domain.com',
44+
'test' => ['one', 'two'],
45+
]);
46+
$response = $this->buildResponse($assertion);
47+
48+
$assertion = $this->buildAssertion([
49+
'name' => 'Doe',
50+
'email_address' => 'doe@domain.com',
51+
'test' => ['three', 'four'],
52+
]);
53+
$response = $this->buildResponse($assertion, $response);
54+
55+
$samlSpResponseToken = $this->buildSamlSpResponseToken($response);
56+
57+
$expectedAttributes = [
58+
'organization' => 'test',
59+
'name' => ['John', 'Doe'],
60+
'email_address' => ['john@domain.com', 'doe@domain.com'],
61+
'test' => ['one', 'two', 'three', 'four'],
62+
];
63+
64+
$simpleAttributeMapper = new SimpleAttributeMapper();
65+
$actualAttributes = $simpleAttributeMapper->getAttributes($samlSpResponseToken);
66+
67+
$this->assertEquals($expectedAttributes, $actualAttributes);
68+
}
69+
70+
public function test_get_attributes_from_multi_attribute_statements_response()
71+
{
72+
$assertion = $this->buildAssertion([
73+
'organization' => 'test',
74+
'name' => 'John',
75+
'email_address' => 'john@domain.com',
76+
'test' => ['one', 'two']
77+
]);
78+
$assertion = $this->buildAssertion([
79+
'name' => 'Doe',
80+
'email_address' => 'doe@domain.com',
81+
'test' => ['three', 'four']
82+
], $assertion);
83+
$response = $this->buildResponse($assertion);
84+
85+
$samlSpResponseToken = $this->buildSamlSpResponseToken($response);
86+
87+
$expectedAttributes = [
88+
'organization' => 'test',
89+
'name' => ['John', 'Doe'],
90+
'email_address' => ['john@domain.com', 'doe@domain.com'],
91+
'test' => ['one', 'two', 'three', 'four'],
92+
];
93+
94+
$simpleAttributeMapper = new SimpleAttributeMapper();
95+
$actualAttributes = $simpleAttributeMapper->getAttributes($samlSpResponseToken);
96+
97+
$this->assertEquals($expectedAttributes, $actualAttributes);
98+
}
99+
100+
/**
101+
* @param Response $response
102+
*
103+
* @return \LightSaml\SpBundle\Security\Authentication\Token\SamlSpResponseToken
104+
*/
105+
private function buildSamlSpResponseToken(Response $response)
106+
{
107+
return new SamlSpResponseToken($response, 'test');
108+
}
109+
110+
/**
111+
* @param Assertion $assertion
112+
* @param Response $response
113+
*
114+
* @return Response
115+
*/
116+
private function buildResponse(Assertion $assertion, Response $response = null)
117+
{
118+
if (null == $response) {
119+
$response = new Response();
120+
}
121+
122+
$response->addAssertion($assertion);
123+
124+
return $response;
125+
}
126+
127+
/**
128+
* @param array $assertionAttributes
129+
* @param Assertion $assertion
130+
*
131+
* @return Assertion
132+
*/
133+
private function buildAssertion(array $assertionAttributes, Assertion $assertion = null)
134+
{
135+
if (null == $assertion) {
136+
$assertion = new Assertion();
137+
}
138+
139+
$assertion->addItem($attributeStatement = new AttributeStatement());
140+
foreach ($assertionAttributes as $attributeName => $attributeValue) {
141+
$attributeStatement->addAttribute(new Attribute($attributeName, $attributeValue));
142+
}
143+
144+
return $assertion;
145+
}
146+
}

0 commit comments

Comments
 (0)