Skip to content

Commit 63e0323

Browse files
committed
Initial import
1 parent 7a21a9f commit 63e0323

10 files changed

Lines changed: 273 additions & 0 deletions

File tree

.codecov.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
coverage:
2+
status:
3+
project: yes
4+
5+
comment:
6+
layout: "diff"
7+
behavior: once
8+
require_changes: true
9+
require_base: no
10+
require_head: yes
11+
branches: null

.php_cs.dist

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
$finder = PhpCsFixer\Finder::create()
3+
->in([
4+
__DIR__ . '/tests',
5+
__DIR__ . '/www',
6+
])
7+
;
8+
return PhpCsFixer\Config::create()
9+
->setRules([
10+
'@PSR2' => true,
11+
'@PSR4' => true,
12+
'@PSR5' => true,
13+
])
14+
->setFinder($finder)
15+
;

.travis.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
sudo: required
2+
3+
language: php
4+
5+
php:
6+
- 5.6
7+
- 7.0
8+
- 7.1
9+
- 7.2
10+
- 7.3
11+
12+
env:
13+
- SIMPLESAMLPHP_VERSION=1.17.*
14+
15+
matrix:
16+
allow_failures:
17+
- php: 7.3
18+
19+
before_script:
20+
- composer require "simplesamlphp/simplesamlphp:${SIMPLESAMLPHP_VERSION}" --no-update
21+
- composer update --no-interaction
22+
- if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then composer require --dev vimeo/psalm:1.1.9; fi
23+
24+
script:
25+
- bin/check-syntax.sh
26+
- if [[ "$TRAVIS_PHP_VERSION" == "5.6" ]]; then php vendor/phpunit/phpunit/phpunit; else php vendor/phpunit/phpunit/phpunit --no-coverage; fi
27+
- if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then vendor/bin/psalm; fi
28+
29+
after_success:
30+
# Codecov, need to edit bash uploader for incorrect TRAVIS_PYTHON_VERSION environment variable matching, at least until codecov/codecov-bash#133 is resolved
31+
- curl -s https://codecov.io/bash > .codecov
32+
- sed -i -e 's/TRAVIS_.*_VERSION/^TRAVIS_.*_VERSION=/' .codecov
33+
- chmod +x .codecov
34+
- if [[ $TRAVIS_PHP_VERSION == "5.6" ]]; then ./.codecov -X gcov; fi
35+
# - if [[ "$TRAVIS_PHP_VERSION" == "5.6" ]]; then bash <(curl -s https://codecov.io/bash); fi

bin/check-syntax.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env bash
2+
3+
PHP='/usr/bin/env php'
4+
RETURN=0
5+
6+
# check PHP files
7+
for FILE in `find tests www -name "*.php"`; do
8+
$PHP -l $FILE > /dev/null 2>&1
9+
if [ $? -ne 0 ]; then
10+
echo "Syntax check failed for ${FILE}"
11+
RETURN=`expr ${RETURN} + 1`
12+
fi
13+
done
14+
15+
exit $RETURN

composer.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"name": "simplesamlphp/simplesamlphp-module-exampleattributeserver",
3+
"description": "An example for SAML attributes queries",
4+
"type": "simplesamlphp-module",
5+
"keywords": ["simplesamlphp", "exampleattributeserver"],
6+
"license": "LGPL-3.0-or-later",
7+
"authors": [
8+
{
9+
"name": "Olav Morken",
10+
"email": "olavmrk@gmail.com"
11+
}
12+
],
13+
"config": {
14+
"preferred-install": {
15+
"simplesamlphp/simplesamlphp": "source",
16+
"*": "dist"
17+
}
18+
},
19+
"autoload": {
20+
"psr-4": {
21+
"SimpleSAML\\Module\\exampleattributeserver\\": "lib/"
22+
}
23+
},
24+
"autoload-dev": {
25+
"psr-4": {
26+
"SimpleSAML\\Test\\Utils\\": "vendor/simplesamlphp/simplesamlphp/tests/Utils"
27+
}
28+
},
29+
"require": {
30+
"php": ">=5.6",
31+
"simplesamlphp/composer-module-installer": "~1.1"
32+
},
33+
"require-dev": {
34+
"simplesamlphp/simplesamlphp": "^1.17",
35+
"phpunit/phpunit": "~5.7"
36+
},
37+
"support": {
38+
"issues": "https://github.com/tvdijen/simplesamlphp-module-exampleattributeserver/issues",
39+
"source": "https://github.com/tvdijen/simplesamlphp-module-exampleattributeserver"
40+
}
41+
}

default-enable

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This file indicates that the default state of this module
2+
is enabled. To disable, create a file named disable in the
3+
same directory as this file.

phpunit.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<phpunit bootstrap="tests/bootstrap.php">
3+
<testsuites>
4+
<testsuite name="The project's test suite">
5+
<directory>tests/</directory>
6+
</testsuite>
7+
</testsuites>
8+
<filter>
9+
<whitelist processUncoveredFilesFromWhitelist="true">
10+
<directory suffix=".php">./lib</directory>
11+
</whitelist>
12+
</filter>
13+
<logging>
14+
<log type="coverage-text" target="php://stdout" showUncoveredFiles="true" />
15+
<log type="coverage-html" target="build/coverage" title="PHP Coveralls" charset="UTF-8" yui="true" highlight="true" lowUpperBound="35" highLowerBound="70" />
16+
<log type="coverage-clover" target="build/logs/clover.xml" />
17+
</logging>
18+
</phpunit>
19+

psalm.xml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0"?>
2+
<psalm
3+
name="SimpleSAMLphp exampleattributeserver module"
4+
useDocblockTypes="true"
5+
totallyTyped="false"
6+
>
7+
<projectFiles>
8+
<directory name="www" />
9+
</projectFiles>
10+
11+
<issueHandlers>
12+
<LessSpecificReturnType errorLevel="info" />
13+
14+
<!-- level 3 issues - slightly lazy code writing, but probably low false-negatives -->
15+
<DeprecatedMethod errorLevel="info" />
16+
17+
<MissingClosureReturnType errorLevel="info" />
18+
<MissingReturnType errorLevel="info" />
19+
<MissingPropertyType errorLevel="info" />
20+
<InvalidDocblock errorLevel="info" />
21+
<MisplacedRequiredParam errorLevel="info" />
22+
23+
<PropertyNotSetInConstructor errorLevel="info" />
24+
<MissingConstructor errorLevel="info" />
25+
<MissingClosureParamType errorLevel="info" />
26+
<MissingParamType errorLevel="info" />
27+
<UnusedClass errorLevel="info" />
28+
<PossiblyUnusedMethod errorLevel="info" />
29+
</issueHandlers>
30+
</psalm>

tests/bootstrap.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
$projectRoot = dirname(__DIR__);
4+
require_once($projectRoot.'/vendor/autoload.php');
5+
6+
// Symlink module into ssp vendor lib so that templates and urls can resolve correctly
7+
$linkPath = $projectRoot.'/vendor/simplesamlphp/simplesamlphp/modules/exampleattributeserver';
8+
if (file_exists($linkPath) === false) {
9+
echo "Linking '$linkPath' to '$projectRoot'\n";
10+
symlink($projectRoot, $linkPath);
11+
}

www/attributeserver.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
$metadata = \SimpleSAML\Metadata\MetaDataStorageHandler::getMetadataHandler();
4+
5+
$binding = \SAML2\Binding::getCurrentBinding();
6+
$query = $binding->receive();
7+
if (!($query instanceof \SAML2\AttributeQuery)) {
8+
throw new \SimpleSAML\Error\BadRequest('Invalid message received to AttributeQuery endpoint.');
9+
}
10+
11+
$idpEntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted');
12+
13+
$issuer = $query->getIssuer();
14+
if ($issuer === null) {
15+
throw new \SimpleSAML\Error\BadRequest('Missing <saml:Issuer> in <samlp:AttributeQuery>.');
16+
} elseif (is_string($issuer)) {
17+
$spEntityId = $issuer;
18+
} else {
19+
$spEntityId = $issuer->getValue();
20+
}
21+
22+
$idpMetadata = $metadata->getMetaDataConfig($idpEntityId, 'saml20-idp-hosted');
23+
$spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote');
24+
25+
// The endpoint we should deliver the message to
26+
$endpoint = $spMetadata->getString('testAttributeEndpoint');
27+
28+
// The attributes we will return
29+
$attributes = [
30+
'name' => ['value1', 'value2', 'value3'],
31+
'test' => ['test'],
32+
];
33+
34+
// The name format of the attributes
35+
$attributeNameFormat = \SAML2\Constants::NAMEFORMAT_UNSPECIFIED;
36+
37+
// Determine which attributes we will return
38+
$returnAttributes = array_keys($query->getAttributes());
39+
if (count($returnAttributes) === 0) {
40+
SimpleSAML\Logger::debug('No attributes requested - return all attributes.');
41+
$returnAttributes = $attributes;
42+
} elseif ($query->getAttributeNameFormat() !== $attributeNameFormat) {
43+
SimpleSAML\Logger::debug('Requested attributes with wrong NameFormat - no attributes returned.');
44+
$returnAttributes = [];
45+
} else {
46+
foreach ($returnAttributes as $name => $values) {
47+
/** @var array $values */
48+
if (!array_key_exists($name, $attributes)) {
49+
// We don't have this attribute
50+
unset($returnAttributes[$name]);
51+
continue;
52+
}
53+
if (count($values) === 0) {
54+
// Return all attributes
55+
$returnAttributes[$name] = $attributes[$name];
56+
continue;
57+
}
58+
59+
// Filter which attribute values we should return
60+
$returnAttributes[$name] = array_intersect($values, $attributes[$name]);
61+
}
62+
}
63+
64+
// $returnAttributes contains the attributes we should return. Send them
65+
$assertion = new \SAML2\Assertion();
66+
$assertion->setIssuer($idpEntityId);
67+
$assertion->setNameId($query->getNameId());
68+
$assertion->setNotBefore(time());
69+
$assertion->setNotOnOrAfter(time() + 300); // 60*5 = 5min
70+
$assertion->setValidAudiences([$spEntityId]);
71+
$assertion->setAttributes($returnAttributes);
72+
$assertion->setAttributeNameFormat($attributeNameFormat);
73+
74+
$sc = new \SAML2\XML\saml\SubjectConfirmation();
75+
$sc->Method = \SAML2\Constants::CM_BEARER;
76+
$sc->SubjectConfirmationData = new \SAML2\XML\saml\SubjectConfirmationData();
77+
$sc->SubjectConfirmationData->setNotOnOrAfter(time() + 300); // 60*5 = 5min
78+
$sc->SubjectConfirmationData->setRecipient($endpoint);
79+
$sc->SubjectConfirmationData->setInResponseTo($query->getId());
80+
$assertion->setSubjectConfirmation([$sc]);
81+
82+
\SimpleSAML\Module\saml\Message::addSign($idpMetadata, $spMetadata, $assertion);
83+
84+
$response = new \SAML2\Response();
85+
$response->setRelayState($query->getRelayState());
86+
$response->setDestination($endpoint);
87+
$response->setIssuer($idpEntityId);
88+
$response->setInResponseTo($query->getId());
89+
$response->setAssertions([$assertion]);
90+
\SimpleSAML\Module\saml\Message::addSign($idpMetadata, $spMetadata, $response);
91+
92+
$binding = new \SAML2\HTTPPost();
93+
$binding->send($response);

0 commit comments

Comments
 (0)