Skip to content

Commit 79b329c

Browse files
authored
Merge pull request #36 from denniscoorn/feature/simple-attribute-mapper
Added a SimpleAttributeMapper
2 parents 4a62c9d + ce1a4cf commit 79b329c

File tree

8 files changed

+239
-4
lines changed

8 files changed

+239
-4
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ before_install:
2020
- echo "session.gc_probability = 0" >> $INI_FILE
2121
- composer self-update
2222
- composer --version
23-
- wget http://get.sensiolabs.org/php-cs-fixer.phar -O php-cs-fixer.phar
23+
- wget https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v1.12.3/php-cs-fixer.phar -O php-cs-fixer.phar
2424

2525
install:
2626
- COMPOSER_ROOT_VERSION=dev-master composer update --prefer-source $COMPOSER_FLAGS

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: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the LightSAML SP-Bundle package.
5+
*
6+
* (c) Milos Tomic <[email protected]>
7+
*
8+
* This source file is subject to the MIT license that is bundled
9+
* with this source code in the file LICENSE.
10+
*/
11+
12+
namespace LightSaml\SpBundle\Security\User;
13+
14+
use LightSaml\Model\Assertion\Assertion;
15+
use LightSaml\Model\Assertion\Attribute;
16+
use LightSaml\Model\Assertion\AttributeStatement;
17+
use LightSaml\SpBundle\Security\Authentication\Token\SamlSpResponseToken;
18+
19+
class SimpleAttributeMapper implements AttributeMapperInterface
20+
{
21+
/**
22+
* @param SamlSpResponseToken $token
23+
*
24+
* @return array
25+
*/
26+
public function getAttributes(SamlSpResponseToken $token)
27+
{
28+
$response = $token->getResponse();
29+
$assertions = $response->getAllAssertions();
30+
31+
return array_reduce($assertions, [$this, 'resolveAttributesFromAssertion'], []);
32+
}
33+
34+
/**
35+
* @param array $attributes
36+
* @param Assertion $assertion
37+
*
38+
* @return array
39+
*/
40+
private function resolveAttributesFromAssertion(array $attributes, Assertion $assertion)
41+
{
42+
$attributeStatements = $assertion->getAllAttributeStatements();
43+
44+
return array_reduce($attributeStatements, [$this, 'resolveAttributesFromAttributeStatement'], $attributes);
45+
}
46+
47+
/**
48+
* @param array $attributes
49+
* @param AttributeStatement $attributeStatement
50+
*
51+
* @return array
52+
*/
53+
private function resolveAttributesFromAttributeStatement(array $attributes, AttributeStatement $attributeStatement)
54+
{
55+
$statementAttributes = $attributeStatement->getAllAttributes();
56+
57+
return array_reduce($statementAttributes, [$this, 'mapAttributeValues'], $attributes);
58+
}
59+
60+
/**
61+
* @param array $attributes
62+
* @param Attribute $attribute
63+
*
64+
* @return array
65+
*/
66+
private function mapAttributeValues(array $attributes, Attribute $attribute)
67+
{
68+
$key = $attribute->getName();
69+
$value = $attribute->getAllAttributeValues();
70+
71+
if (!array_key_exists($key, $attributes) && count($value) === 1) {
72+
$value = array_shift($value);
73+
}
74+
75+
if (array_key_exists($key, $attributes)) {
76+
$currentValue = (is_array($attributes[$key]) ? $attributes[$key] : [$attributes[$key]]);
77+
78+
$value = array_merge($currentValue, $value);
79+
}
80+
81+
$attributes[$key] = $value;
82+
83+
return $attributes;
84+
}
85+
}

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' => '[email protected]',
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' => '[email protected]',
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' => '[email protected]',
44+
'test' => ['one', 'two'],
45+
]);
46+
$response = $this->buildResponse($assertion);
47+
48+
$assertion = $this->buildAssertion([
49+
'name' => 'Doe',
50+
'email_address' => '[email protected]',
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' => ['[email protected]', '[email protected]'],
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' => '[email protected]',
76+
'test' => ['one', 'two']
77+
]);
78+
$assertion = $this->buildAssertion([
79+
'name' => 'Doe',
80+
'email_address' => '[email protected]',
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' => ['[email protected]', '[email protected]'],
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)