diff --git a/.gitignore b/.gitignore index 1dbeb38..cb2c4db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,9 @@ -sp.key -sp.crt -vendor -tmp -www/settings.php -www2/settings.php -config.yaml .directory +.vscode +.DS_Store AuthnRequest.patched LogoutRequest.patched +vendor +example/sp.key +example/sp.crt +example/idp_metadata/*.xml diff --git a/AuthnRequest.diff b/AuthnRequest.diff index e11c2e7..2aea923 100644 --- a/AuthnRequest.diff +++ b/AuthnRequest.diff @@ -1,9 +1,13 @@ -56,57c56 +72,73c72 < Format="{$nameIDPolicyFormat}" < AllowCreate="true" /> --- > Format="{$nameIDPolicyFormat}" /> -130c129 +143,145c142,144 +< ProtocolBinding="{$spData['assertionConsumerService']['binding']}" +< AssertionConsumerServiceURL="{$acsUrl}"> < {$spEntityId} --- -> {$spEntityId} +> AssertionConsumerServiceIndex="1" +> AttributeConsumingServiceIndex="1"> +> {$spEntityId} diff --git a/LogoutRequest.diff b/LogoutRequest.diff index 19a77dc..8e9f466 100644 --- a/LogoutRequest.diff +++ b/LogoutRequest.diff @@ -1,4 +1,4 @@ -107c107 +128c128 < {$spEntityId} --- -> {$spEntityId} +> {$spEntityId} diff --git a/Makefile b/Makefile index 17dce19..e78cd76 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,23 @@ -all: sp.key AuthnRequest.patched LogoutRequest.patched - # clean up twig cache - rm -rf tmp - mkdir -p tmp - ./bin/configure.php > www/settings.php - cp www/settings.php www2/settings.php +all: example/sp.key AuthnRequest.patched LogoutRequest.patched AuthnRequest.patched: TO_PATCH:=vendor/onelogin/php-saml/src/Saml2/AuthnRequest.php AuthnRequest.patched: AuthnRequest.diff - if [ -e $@ ]; then patch -R "${TO_PATCH}" $@; fi - patch -N "${TO_PATCH}" $< - cp $< $@ + if [ -e $@ ]; then patch -R vendor/onelogin/php-saml/src/Saml2/AuthnRequest.php $@; fi + patch -N vendor/onelogin/php-saml/src/Saml2/AuthnRequest.php $< + cp AuthnRequest.diff $@ LogoutRequest.patched: TO_PATCH=vendor/onelogin/php-saml/src/Saml2/LogoutRequest.php LogoutRequest.patched: LogoutRequest.diff - if [ -e $@ ]; then patch -R "$(TO_PATCH)" $@; fi - patch -N "${TO_PATCH}" $< - cp $< $@ + if [ -e $@ ]; then patch -R vendor/onelogin/php-saml/src/Saml2/LogoutRequest.php $@; fi + patch -N vendor/onelogin/php-saml/src/Saml2/LogoutRequest.php $< + cp LogoutRequest.diff $@ -sp.key: - openssl req -x509 -nodes -sha256 -days 365 -newkey rsa:2048 -subj "/C=IT/ST=Italy/L=Rome/O=testenv2/CN=localhost" -keyout sp.key -out sp.crt +example/sp.key: + openssl req -x509 -nodes -sha256 -days 365 -newkey rsa:2048 -subj "/C=IT/ST=Italy/L=Rome/O=testenv2/CN=localhost" -keyout example/sp.key -out example/sp.crt clean: - rm -rf tmp vendor www/settings.php AuthnRequest.patched LogoutRequest.patched + rm -rf vendor + rm -f AuthnRequest.patched + rm -f LogoutRequest.patched + rm -f example/idp_metadata/*.xml + rm -f example/sp.crt example/sp.key diff --git a/README.md b/README.md index 22e6ae7..dd3f84a 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,30 @@ +SPID + +[![Join the #spid-perl channel](https://img.shields.io/badge/Slack%20channel-%23spid--perl-blue.svg?logo=slack)](https://developersitalia.slack.com/messages/C7ESTMQDQ) +[![Get invited](https://slack.developers.italia.it/badge.svg)](https://slack.developers.italia.it/) +[![SPID on forum.italia.it](https://img.shields.io/badge/Forum-SPID-blue.svg)](https://forum.italia.it/c/spid) + +> ⚠️ **WORK IN PROGRESS (but should be useable)** ⚠️ + # spid-php2 +PHP package for SPID authentication based on [php-saml](https://github.com/onelogin/php-saml). -Software Development Kit (SDK) for easy SPID SSO integration based on [php-saml](https://github.com/onelogin/php-saml). +This PHP package is aimed at implementing SPID **Service Providers**. [SPID](https://www.spid.gov.it/) is the Italian digital identity system, which enables citizens to access all public services with a single set of credentials. This package provides a layer of abstraction over the SAML protocol by exposing just the subset required in order to implement SPID authentication in a web application. -This component acts as a SPID SP (Service Provider) and logs you in via an external IDP (IDentity Provider). It does not support Attribute Authority. +Features: +- **routing-agnostic**, can be integrated in any web framework / CMS +- **sessionless** (apart from a short-lived internal session used to store the request ID and IdP name until the IdP responds) +- does not currently support Attribute Authority (AA). -Alternative SDK: [spid-php](https://github.com/italia/spid-php) based on [SimpleSAMLphp](https://simplesamlphp.org/). +Alternatives for PHP: +- [spid-php](https://github.com/italia/spid-php) based on [SimpleSAMLphp](https://simplesamlphp.org/) +- [spid-php3](https://github.com/simevo/spid-php3), a lean implementation that does not rely on external SAML packages -## Features +Alternatives for other languages: +- [spid-perl](https://github.com/italia/spid-perl) +- [spid-ruby](https://github.com/italia/spid-ruby) + +## Compliance |
_Compliance with [SPID regulations](http://www.agid.gov.it/sites/default/files/circolari/spid-regole_tecniche_v1.pdf) (for Service Providers)_|status (! = TODO)|comments| |:---|:---|:---| @@ -73,84 +91,143 @@ Alternative SDK: [spid-php](https://github.com/italia/spid-php) based on [Simple |generation of AttributeQuery XML||Attribute Authority is unsupported| |SOAP binding (client)||Attribute Authority is unsupported| -## Prerequisites +## Repository layout -Tested on Debian 10.x buster with PHP 7.2. +* [bin/](bin/) auxiliary scripts +* [example/](example/) contains a demo application +* [src/](src/) contains the implementation +* [test/](test/) will contain the unit tests -Perform these steps to install the prerequisites: -``` +## Getting Started + +Tested on Debian 9.5 (stretch, current stable) and 10 (buster, current unstable) with PHP 7-0-7.2. + +### Prerequisites + +```sh sudo apt install composer make openssl php-curl php-zip php-xml ``` -if you have PHP <= 7.1 (i.e. Debian 9.4 stretch or earlier), then you also need: -``` -apt install php-mcrypt -``` -Then install PHP dependencies; if you have PHP 7.2 (i.e. Debian 10.x buster): +### Configuring and Installing + +Before using this package, you must: + +1. Install prerequisites with composer + +2. Download and verify the Identity Provider (IdP) metadata files; it is advised to place them in a separate directory, for example [example/idp_metadata/](example/idp_metadata/). A convenience tool is provided for this purpose: [bin/download_idp_metadata.php](bin/download_idp_metadata.php). + +3. Generate key and certificate for the Service Provider (SP) and patch the php-saml package to comply with the SPID standard. To do that, you can use the provided [Makefile](Makefile). + +All steps can be performed with: +```sh +composer install --no-dev +pushd example && ../bin/download_idp_metadata.php && popd +make ``` -composer install + +**NOTE**: during testing, it is highly adviced to use the test Identity Provider [spid-testenv2](https://github.com/italia/spid-testenv2). + +### Usage + +All classes provided by this package reside in the `Italia\Spid2` namespace. + +Load them using the composer-generated autoloader: +```php +require_once(__DIR__ . "/../vendor/autoload.php"); ``` -if you have PHP <= 7.1 (i.e. Debian 9.4 stretch or earlier), then use the v2.x branch of php-saml: + +The main class is `Italia\Spid2\Sp` (service provider), sample instantiation: + +```php +$base = "http://localhost:8000"; +$settings = [ + 'spEntityId' => $base, + 'spAcsUrl' => $base . "/acs.php", + 'spSloUrl' => $base . "/logout.php", + 'spKeyFile' => "./sp.key", + 'spCrtFile' => "./sp.crt", + 'idpMetadataFolderPath' => $home . "/idp_metadata", + 'idpList' => array( + 'testenv2' + ) + ]; +$sp = new Italia\Spid2\Sp($settings); ``` -rm composer.* -composer require onelogin/php-saml -composer require twig/twig -composer require symfony/yaml + +The service provider is now ready for use, as in: +```php +$idp_name = 'idp_1'; +$return_to = 'https://example.com/return_to_url'; +$spid_level = 1; +$sp->login($idp_name, $return_to, $spid_level); +$attributes = $sp->getAttributes(); +var_dump($attributes); +$sp->logout(); ``` -## Demo +### Example -The demo is based on php-saml demo1. +A basic demo application is provided in the [example/](example/) directory. -To set it up and run it: +To use: -1. copy `config.yaml.example` to `config.yaml` and customize it as required (you should at least set `idp_metadata_url` to match your IDP metadata endpoint) +1. in `example/settings.php`: -2. auto-configure: - ``` - make - ``` + - adapt the base url (`$base`) to your needs (use am IP address or a hostname that is visible to the IdP) + - make sure the IdP metadata corresponding to the IdPs listed in the `idpList` key are present in `example/idp_metadata` + +2. in `example/login.php` change the IdP that will be used to login 3. Start PHP's builtin webserver in the root of the repo: - ``` - php -S localhost:8000 -t www - ``` - if you have php-saml v2.x (i.e. Debian 9.4 stretch), then run it from the www2 dir: - ``` - php -S localhost:8000 -t www2 + ```sh + php -S 0.0.0.0:8000 -t example ``` -4. visit http://localhost:8000/metadata.php to get the SP (Service Provider) metadata, then copy these over to the IDP +4. visit http://localhost:8000/metadata.php to get the SP (Service Provider) metadata, then copy these over to the IdP 5. visit: http://localhost:8000 and click `login`. +This screencast shows what you should see if all goes well: + +![img](images/screencast.gif) + ## Troubleshooting -- install a browser plugin to trace SAML messages: +It is advised to install a browser plugin to trace SAML messages: - - Firefox: +- Firefox: - - [SAML-tracer by Olav Morken, Jaime Perez](https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/) - - [SAML Message Decoder by Magnus Suther](https://addons.mozilla.org/en-US/firefox/addon/saml-message-decoder-extension/) + - [SAML-tracer by Olav Morken, Jaime Perez](https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/) + - [SAML Message Decoder by Magnus Suther](https://addons.mozilla.org/en-US/firefox/addon/saml-message-decoder-extension/) - - Chrome/Chromium: +- Chrome/Chromium: - - [SAML Message Decoder by Magnus Suther](https://chrome.google.com/webstore/detail/saml-message-decoder/mpabchoaimgbdbbjjieoaeiibojelbhm) - - [SAML Chrome Panel by MLai](https://chrome.google.com/webstore/detail/saml-chrome-panel/paijfdbeoenhembfhkhllainmocckace) - - [SAML DevTools extension by stefan.rasmusson.as](https://chrome.google.com/webstore/detail/saml-devtools-extension/jndllhgbinhiiddokbeoeepbppdnhhio) + - [SAML Message Decoder by Magnus Suther](https://chrome.google.com/webstore/detail/saml-message-decoder/mpabchoaimgbdbbjjieoaeiibojelbhm) + - [SAML Chrome Panel by MLai](https://chrome.google.com/webstore/detail/saml-chrome-panel/paijfdbeoenhembfhkhllainmocckace) + - [SAML DevTools extension by stefan.rasmusson.as](https://chrome.google.com/webstore/detail/saml-devtools-extension/jndllhgbinhiiddokbeoeepbppdnhhio) -- use the [SAML Developer Tools](https://www.samltool.com/online_tools.php) provided by onelogin to understand what is going on +In addition, you can use the [SAML Developer Tools](https://www.samltool.com/online_tools.php) provided by onelogin to understand what is going on -## Contributing +## Testing + +### Unit tests + +TODO + +Unit tests will be performed with PHPunit. -Your code **should** comply with the [PSR-2: Coding Style Guide](https://www.php-fig.org/psr/psr-2/). -Check your changes with: +### Linting + +This project complies with the [PSR-2: Coding Style Guide](https://www.php-fig.org/psr/psr-2/). + +Lint the code with: ``` -./vendor/bin/phpcs --standard=PSR2 bin/configure.php -... +./vendor/bin/phpcs --standard=PSR2 xxx.php ``` -You **must** use the [git-flow workflow](https://danielkummer.github.io/git-flow-cheatsheet/). +## Contributing + +For your contributions please use the [git-flow workflow](https://danielkummer.github.io/git-flow-cheatsheet/). ## Legalese diff --git a/bin/configure.php b/bin/configure.php deleted file mode 100755 index c64a027..0000000 --- a/bin/configure.php +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/php - './tmp', -)); -$template = $twig->load('settings.tpl'); - -// read configuration -$yaml = \Symfony\Component\Yaml\Yaml::parseFile('config.yaml'); -foreach ($yaml as $k => $v) { - $$k = $v; -} - -# read SP key and cert from the files generated by openssl -$sp_key_raw = file_get_contents($sp_key_file); -$sp_cert_raw = file_get_contents($sp_cert_file); - -# get rid of '-----' lines -function clean_openssl($k) -{ - $ck = ''; - foreach (preg_split("/((\r?\n)|(\r\n?))/", $k) as $l) { - if (strpos($l, '-----') === false) { - $ck .= $l; - } - } - return $ck; -} - -$sp_key = clean_openssl($sp_key_raw); -$sp_cert = clean_openssl($sp_cert_raw); - -# retrieve the IDP metadata and extract information -$ch = curl_init(); -curl_setopt($ch, CURLOPT_URL, $idp_metadata_url); -curl_setopt($ch, CURLOPT_FAILONERROR, 1); -curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); -curl_setopt($ch, CURLOPT_TIMEOUT, 15); -curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); -curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); -$data = curl_exec($ch); -curl_close($ch); -$xml = new SimpleXMLElement($data); -$idp_entityid = $xml->xpath('//ns0:EntityDescriptor/@entityID')[0]; -$idp_sso = $xml->xpath('//ns0:SingleSignOnService/@Location')[0]; -$idp_slo = $xml->xpath('//ns0:SingleLogoutService/@Location')[0]; -$idp_cert = $xml->xpath('//ns1:X509Certificate')[0]; - -echo $template->render(array( - 'sp_base' => $sp_base, - 'sp_cert' => $sp_cert, - 'sp_key' => $sp_key, - 'idp_entityid' => $idp_entityid, - 'idp_sso' => $idp_sso, - 'idp_slo' => $idp_slo, - 'idp_cert' => $idp_cert, -)); diff --git a/bin/download_idp_metadata.php b/bin/download_idp_metadata.php new file mode 100755 index 0000000..5c51844 --- /dev/null +++ b/bin/download_idp_metadata.php @@ -0,0 +1,39 @@ +#!/usr/bin/php + +// License: BSD 3-Clause + +$idp_list_url = 'https://registry.spid.gov.it/assets/data/idp.json'; +$ch = curl_init(); +curl_setopt($ch, CURLOPT_URL, $idp_list_url); +curl_setopt($ch, CURLOPT_FAILONERROR, 1); +curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); +curl_setopt($ch, CURLOPT_TIMEOUT, 15); +echo "Contacting $idp_list_url" . PHP_EOL; +$json = curl_exec($ch); +curl_close($ch); +$idps = json_decode($json); + +foreach ($idps->data as $idp) { + $metadata_url = $idp->metadata_url; + $ipa_entity_code = $idp->ipa_entity_code; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $metadata_url); + curl_setopt($ch, CURLOPT_FAILONERROR, 1); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_TIMEOUT, 15); + echo "Contacting $metadata_url" . PHP_EOL; + $xml = curl_exec($ch); + curl_close($ch); + $file = "idp_metadata/$ipa_entity_code.xml"; + file_put_contents($file, $xml); +} diff --git a/composer.json b/composer.json index b598c44..50f2290 100644 --- a/composer.json +++ b/composer.json @@ -1,9 +1,14 @@ { "name": "italia/spid-php2", "require": { - "onelogin/php-saml": "3.0.0.x-dev", - "twig/twig": "^2.4", - "symfony/yaml": "^4.1", - "squizlabs/php_codesniffer": "*" + "onelogin/php-saml": "3.0.0.x-dev" + }, + "require-dev": { + "squizlabs/php_codesniffer": "^3.3" + }, + "autoload": { + "psr-4": { + "Italia\\Spid2\\": "src/" + } } -} +} \ No newline at end of file diff --git a/composer.lock b/composer.lock index 4a6f9a3..8d61fef 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d0f2b5c5b2a0656dd94e55792b743bdf", + "content-hash": "0e934f11b83adea144b2a84c424aaf82", "packages": [ { "name": "onelogin/php-saml", @@ -12,12 +12,12 @@ "source": { "type": "git", "url": "https://github.com/onelogin/php-saml.git", - "reference": "c98647228e5260004fe6bc31158f322ea94c152c" + "reference": "e0c5827d7ccff72b6cf19f55420cad0e4eea5faf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/onelogin/php-saml/zipball/c98647228e5260004fe6bc31158f322ea94c152c", - "reference": "c98647228e5260004fe6bc31158f322ea94c152c", + "url": "https://api.github.com/repos/onelogin/php-saml/zipball/e0c5827d7ccff72b6cf19f55420cad0e4eea5faf", + "reference": "e0c5827d7ccff72b6cf19f55420cad0e4eea5faf", "shasum": "" }, "require": { @@ -54,7 +54,7 @@ "onelogin", "saml" ], - "time": "2018-06-19T00:33:13+00:00" + "time": "2018-08-02T15:43:25+00:00" }, { "name": "robrichards/xmlseclibs", @@ -95,19 +95,21 @@ "xmldsig" ], "time": "2017-08-31T09:27:07+00:00" - }, + } + ], + "packages-dev": [ { "name": "squizlabs/php_codesniffer", - "version": "3.3.0", + "version": "3.3.1", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "d86873af43b4aa9d1f39a3601cc0cfcf02b25266" + "reference": "628a481780561150481a9ec74709092b9759b3ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d86873af43b4aa9d1f39a3601cc0cfcf02b25266", - "reference": "d86873af43b4aa9d1f39a3601cc0cfcf02b25266", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/628a481780561150481a9ec74709092b9759b3ec", + "reference": "628a481780561150481a9ec74709092b9759b3ec", "shasum": "" }, "require": { @@ -145,249 +147,9 @@ "phpcs", "standards" ], - "time": "2018-06-06T23:58:19+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", - "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - }, - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "time": "2018-04-30T19:57:29+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "3296adf6a6454a050679cde90f95350ad604b171" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", - "reference": "3296adf6a6454a050679cde90f95350ad604b171", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "time": "2018-04-26T10:06:28+00:00" - }, - { - "name": "symfony/yaml", - "version": "v4.1.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "80e4bfa9685fc4a09acc4a857ec16974a9cd944e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/80e4bfa9685fc4a09acc4a857ec16974a9cd944e", - "reference": "80e4bfa9685fc4a09acc4a857ec16974a9cd944e", - "shasum": "" - }, - "require": { - "php": "^7.1.3", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.1-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2018-05-30T07:26:09+00:00" - }, - { - "name": "twig/twig", - "version": "v2.4.8", - "source": { - "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "7b604c89da162034bdf4bb66310f358d313dd16d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/7b604c89da162034bdf4bb66310f358d313dd16d", - "reference": "7b604c89da162034bdf4bb66310f358d313dd16d", - "shasum": "" - }, - "require": { - "php": "^7.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "require-dev": { - "psr/container": "^1.0", - "symfony/debug": "^2.7", - "symfony/phpunit-bridge": "^3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "psr-0": { - "Twig_": "lib/" - }, - "psr-4": { - "Twig\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" - }, - { - "name": "Twig Team", - "homepage": "http://twig.sensiolabs.org/contributors", - "role": "Contributors" - } - ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "http://twig.sensiolabs.org", - "keywords": [ - "templating" - ], - "time": "2018-04-02T09:24:19+00:00" + "time": "2018-07-26T23:47:18+00:00" } ], - "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": { diff --git a/config.yaml.example b/config.yaml.example deleted file mode 100644 index 2b9ce93..0000000 --- a/config.yaml.example +++ /dev/null @@ -1,12 +0,0 @@ ---- -# SERVICE PROVIDER CONFIGURATION - -# SP base URL -sp_base: "http://sp2.simevo.com" - -# SP key and certificate location -sp_key_file: "sp.key" -sp_cert_file: "sp.crt" - -# URL for IDP metadata -idp_metadata_url: "https://idp.simevo.com/metadata" diff --git a/example/acs.php b/example/acs.php new file mode 100644 index 0000000..e10fc2d --- /dev/null +++ b/example/acs.php @@ -0,0 +1,19 @@ +isAuthenticated()) { + $attributes = $sp->getAttributes(); + echo "logged in !" . PHP_EOL; + foreach ($attributes as $key => $attribute) { + echo $key .": " . $attribute . "
"; + } + + echo '

Logout

'; +} else { + echo "not logged in !" . PHP_EOL; + echo '

Login

'; +} diff --git a/example/idp_metadata/put_idp_metadata_here b/example/idp_metadata/put_idp_metadata_here new file mode 100644 index 0000000..e69de29 diff --git a/example/idps.php b/example/idps.php new file mode 100644 index 0000000..78793b7 --- /dev/null +++ b/example/idps.php @@ -0,0 +1,10 @@ +getSupportedIdps() as $key => $idp) { + echo $key . ' - ' . $idp . '
'; +} diff --git a/example/index.php b/example/index.php new file mode 100644 index 0000000..5681d2b --- /dev/null +++ b/example/index.php @@ -0,0 +1,7 @@ +Login

'; +echo '

Show the SP metadata

'; +echo '

Show the supported IdPs

'; +echo '

Logout

'; +echo '

Assertion Consuming Service

'; diff --git a/example/login.php b/example/login.php new file mode 100644 index 0000000..ea97e8e --- /dev/null +++ b/example/login.php @@ -0,0 +1,12 @@ +isAuthenticated() === false) { + $sp->login("testenv2"); +} else { + echo "Already logged in!"; +} diff --git a/example/logout.php b/example/logout.php new file mode 100644 index 0000000..293c6ad --- /dev/null +++ b/example/logout.php @@ -0,0 +1,13 @@ +isAuthenticated()) { + $sp->logout(); +} else { + echo "Logged out!"; + echo '

Go back

'; +} diff --git a/example/metadata.php b/example/metadata.php new file mode 100644 index 0000000..f752505 --- /dev/null +++ b/example/metadata.php @@ -0,0 +1,11 @@ +getSPMetadata(); + +header('Content-Type: text/xml'); +echo $metadata; diff --git a/example/settings.php b/example/settings.php new file mode 100644 index 0000000..a7592b6 --- /dev/null +++ b/example/settings.php @@ -0,0 +1,25 @@ + $base, // preferred: https protocol, no path, no trailing slash + 'spAcsUrl' => $base . "/acs.php", // full url + 'spSloUrl' => $base . "/logout.php", // full url + 'spKeyFile' => "./sp.key", // full or relative path + 'spCrtFile' => "./sp.crt", // full or relative path + 'idpMetadataFolderPath' => "./idp_metadata", // full or relative path + // for each item in the idpList array, a file with the same name and xml extension + // must be present in the idpMetadataFolderPath directory + 'idpList' => array( + 'idp_1', + 'idp_2', + 'idp_3', + 'idp_4', + 'idp_5', + 'idp_6', + 'idp_7', + 'idp_8', + 'testenv2' + ) + ]; diff --git a/images/screencast.gif b/images/screencast.gif new file mode 100644 index 0000000..daed10e Binary files /dev/null and b/images/screencast.gif differ diff --git a/saml-schema-assertion-2.0.xsd b/saml-schema-assertion-2.0.xsd deleted file mode 100644 index bbad992..0000000 --- a/saml-schema-assertion-2.0.xsd +++ /dev/null @@ -1,283 +0,0 @@ - - - - - - - Document identifier: saml-schema-assertion-2.0 - Location: http://docs.oasis-open.org/security/saml/v2.0/ - Revision history: - V1.0 (November, 2002): - Initial Standard Schema. - V1.1 (September, 2003): - Updates within the same V1.0 namespace. - V2.0 (March, 2005): - New assertion schema for SAML V2.0 namespace. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/saml-schema-metadata-SPID-SP.xsd b/saml-schema-metadata-SPID-SP.xsd deleted file mode 100644 index c0ca8ad..0000000 --- a/saml-schema-metadata-SPID-SP.xsd +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - Document identifier: Location: Revision history: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Config/OneLoginConfig.php b/src/Config/OneLoginConfig.php new file mode 100644 index 0000000..7af62da --- /dev/null +++ b/src/Config/OneLoginConfig.php @@ -0,0 +1,154 @@ +spAcsUrl = $this->spEntityId . '/index.php?acs'; + $this->spSloUrl = $this->spEntityId . '/index.php?sls'; + } + + public function getSettings() + { + return array( + // If 'strict' is True, then the PHP Toolkit will reject unsigned + // or unencrypted messages if it expects them to be signed or encrypted. + // Also it will reject the messages if the SAML standard is not strictly + // followed: Destination, NameId, Conditions ... are validated too. + 'strict' => true, + + // Enable debug mode (to print errors). + 'debug' => true, + + 'sp' => array( + 'entityId' => $this->spEntityId, + 'assertionConsumerService' => array( + 'url' => $this->spAcsUrl, + ), + 'singleLogoutService' => array( + 'url' => $this->spSloUrl, + ), + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient', + 'x509cert' => $this->spCrtFile, + 'privateKey' => $this->spKeyFile, + "attributeConsumingService"=> array( + "serviceName" => "SP test", + "serviceDescription" => "Test Service", + "requestedAttributes" => array( + array ( + 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_BASIC, + 'isRequired' => true, + 'name' => 'name', + 'friendlyName' => 'Nome' + ), + array ( + 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_BASIC, + 'isRequired' => true, + 'name' => 'familyName', + 'friendlyName' => 'Cognome' + ), + array ( + 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_BASIC, + 'isRequired' => true, + 'name' => 'fiscalNumber', + 'friendlyName' => 'Codice Fiscale' + ), + ) + ), + ), + 'idp' => array( + 'entityId' => $this->idpEntityId, + 'singleSignOnService' => array( + 'url' => $this->idpSSO, + ), + 'singleLogoutService' => array( + 'url' => $this->idpSLO, + ), + 'x509cert' => $this->idpCertValue, + ), + 'security' => array( + 'authnRequestsSigned' => true, + 'logoutRequestSigned' => true, + 'logoutResponseSigned' => true, + 'signMetadata' => true, + 'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', + 'requestedAuthnContext' => array('https://www.spid.gov.it/SpidL' . $this->level), + ), + ); + } + + public function updateSettings($settings) + { + foreach ($settings as $key => $value) { + if (!property_exists(OneLoginConfig::class, $key)) { + continue; + } + if (in_array($key, $this->is_not_updatable)) { + continue; + } + + $this->{$key} = $value; + } + // Get .key and .cert files content and add it to configuration + if (!file_exists($this->spKeyFile) || !file_exists($this->spCrtFile)) { + throw new \Exception("The path for .key ($this->spKeyFile) and .cert ($this->spCrtFile) files is invalid", 1); + } + $sp = SpHelper::getSpCert($this->spKeyFile, $this->spCrtFile); + $this->updateSpData($sp); + return $this->getSettings(); + } + + public function updateIdpMetadata($idpName) + { + if (!in_array($idpName, $this->idpList)) { + throw new \Exception("Unsupported IDP $idpName", 1); + } + $metadata = IdpHelper::getMetadata($idpName, $this->idpMetadataFolderPath); + foreach ($metadata as $key => $value) { + if (property_exists(OneLoginConfig::class, $key) && strpos($key, "idp") !== false) { + $this->{$key} = $value; + } + } + return $this->getSettings(); + } + + public function updateSpData($sp) + { + if (!is_array($sp)) { + throw new \Exception("Invalid SP certificate data provided", 1); + } + + $this->spKeyFile = $sp['key']; + $this->spCrtFile = $sp['cert']; + + return $this->getSettings(); + } +} diff --git a/src/Helpers/IdpHelper.php b/src/Helpers/IdpHelper.php new file mode 100644 index 0000000..5662ec8 --- /dev/null +++ b/src/Helpers/IdpHelper.php @@ -0,0 +1,27 @@ +registerXPathNamespace('md', 'urn:oasis:names:tc:SAML:2.0:metadata'); + $xml->registerXPathNamespace('ds', 'http://www.w3.org/2000/09/xmldsig#'); + + $metadata = array(); + $metadata['idpEntityId'] = $xml->attributes()->entityID->__toString(); + $metadata['idpSSO'] = $xml->xpath('//md:SingleSignOnService')[0]->attributes()->Location->__toString(); + $metadata['idpSLO'] = $xml->xpath('//md:SingleLogoutService')[0]->attributes()->Location->__toString(); + $metadata['idpCertValue'] = $xml->xpath('//ds:X509Certificate')[0]->__toString(); + + return $metadata; + } +} diff --git a/src/Helpers/SpHelper.php b/src/Helpers/SpHelper.php new file mode 100644 index 0000000..264eae3 --- /dev/null +++ b/src/Helpers/SpHelper.php @@ -0,0 +1,28 @@ +mode = $mode; + $this->settings = $settings; + + $this->initStrategy(); + } + + private function initStrategy($idpName = null) + { + switch ($this->mode) { + case 'onelogin': + $this->strategy = new SpOneLogin($this->settings, $idpName); + break; + default: + $this->strategy = new SpOneLogin($this->settings, $idpName); + break; + } + } + + public function getSPMetadata() + { + return $this->strategy->getSPMetadata(); + } + + public function getSupportedIdps() + { + return $this->strategy->getSupportedIdps(); + } + + public function isAuthenticated() + { + return $this->strategy->isAuthenticated(); + } + + public function login($idpName, $redirectTo = '', $level = 1) + { + if (is_null($this->strategy)) { + $this->initStrategy($idpName); + } + return $this->strategy->login($idpName, $redirectTo); + } + + public function logout() + { + return $this->strategy->logout(); + } + + public function getAttributes() + { + return $this->strategy->getAttributes(); + } +} diff --git a/src/Strategy/SpOneLogin.php b/src/Strategy/SpOneLogin.php new file mode 100644 index 0000000..958bd4d --- /dev/null +++ b/src/Strategy/SpOneLogin.php @@ -0,0 +1,186 @@ +idpName = $idpName; + $this->settings = $settings; + $this->init(); + } + + private function init() + { + $settingsHelper = new OneLoginConfig(); + $this->settingsHelper = $settingsHelper; + if (!is_null($this->settings)) { + $diff = array_diff_key($this->settings, get_object_vars($settingsHelper)); + if (!empty($diff)) { + $message = "The following keys are invalid for the provided settings array: "; + $first = true; + foreach ($diff as $key => $value) { + if ($first) { + $message .= $key; + } + $first = false; + $message .= ", " . $key; + } + throw new \Exception($message, 1); + } + // if the user doesn't supply a preferred IDP, a default one is used + $this->settings['idpList'] = $this->getSupportedIdps(); + $settingsHelper->updateSettings($this->settings); + } + $this->idpName = is_null($this->idpName) ? $this->settings['idpList'][0] : $this->idpName; + $this->settingsHelper->updateIdpMetadata($this->idpName); + $this->oneloginSettings = new Settings($this->settingsHelper->getSettings()); + $this->auth = new Auth($this->settingsHelper->getSettings()); + } + + private function changeIdp($idpName) + { + if ($this->idpName != $idpName) { + $this->idpName = $idpName; + $this->init(); + } + } + + public function getSPMetadata() + { + $oneloginSettings = new Settings($this->settingsHelper->getSettings()); + $metadata = $oneloginSettings->getSPMetadata(); + + $errors = $oneloginSettings->validateMetadata($metadata); + if (!empty($errors)) { + throw new OneLogin_Saml2_Error( + 'Invalid SP metadata: '.implode(', ', $errors), + OneLogin_Saml2_Error::METADATA_SP_INVALID + ); + } + return $metadata; + } + + public function getSupportedIdps() + { + if (array_key_exists('idpList', $this->settings) && is_array($this->settings['idpList'])) { + return $this->settings['idpList']; + } + + $dir = $this->settings['idpMetadataFolderPath']; + $idp_files = glob($dir . '*.{xml}', GLOB_BRACE); + $idps = array(); + foreach ($idp_files as $key => $value) { + $xml = simplexml_load_file($value); + $idps[basename($value, '.xml')] = $xml->attributes()->entityID->__toString(); + } + return $idps; + } + + public function isAuthenticated() + { + if (isset($_SESSION) && isset($_SESSION['idpName'])) { + $this->changeIdp($_SESSION['idpName']); + } + + if (isset($_SESSION) && isset($_SESSION['LogoutRequestID'])) { + $this->auth->processSLO(false, $_SESSION['LogoutRequestID']); + unset($_SESSION['LogoutRequestID']); + + $errors = $this->auth->getErrors(); + if (!empty($errors)) { + return $errors; + } + return false; + } + + if (isset($_SESSION['authReqID']) && isset($_POST['SAMLResponse'])) { + $this->auth->processResponse($_SESSION['authReqID']); + unset($_SESSION['authReqID']); + $errors = $this->auth->getErrors(); + + if (!empty($errors)) { + return $errors; + } + + $this->userdata = array(); + $this->userdata['samlUserdata'] = $this->auth->getAttributes(); + $this->userdata['samlNameId'] = $this->auth->getNameId(); + $this->userdata['samlNameIdFormat'] = $this->auth->getNameIdFormat(); + $this->userdata['samlSessionIndex'] = $this->auth->getSessionIndex(); + foreach ($this->userdata['samlUserdata'] as $key => &$value) { + if (is_array($value)) { + $value = $value[0]; + } + } + } + if ($this->auth->isAuthenticated() === false) { + return false; + } + return true; + } + + public function login($idpName, $redirectTo = '', $level = 1) + { + $this->settings['level'] = $level; + $this->changeIdp($idpName); + + if ($this->auth->isAuthenticated()) { + return false; + } + + $ssoBuiltUrl = $this->auth->login($redirectTo, array(), false, false, true); + + $this->authRequestID = $this->auth->getLastRequestID(); + $_SESSION['authReqID'] = $this->auth->getLastRequestID(); + $_SESSION['idpName'] = $idpName; + + header('Pragma: no-cache'); + header('Cache-Control: no-cache, must-revalidate'); + header('Location: ' . $ssoBuiltUrl); + exit(); + } + + public function logout() + { + if ($this->auth->isAuthenticated() === false) { + return false; + } + $this->auth->logout(); + + $sloBuiltUrl = $this->auth->logout(null, array(), null, null, true); + $_SESSION['LogoutRequestID'] = $this->auth->getLastRequestID(); + + header('Pragma: no-cache'); + header('Cache-Control: no-cache, must-revalidate'); + header('Location: ' . $sloBuiltUrl); + exit(); + } + + public function getAttributes() + { + if (is_null($this->userdata) || !array_key_exists('samlUserdata', $this->userdata)) { + return array(); + } + return $this->userdata['samlUserdata']; + } +} diff --git a/templates/settings.tpl b/templates/settings.tpl deleted file mode 100644 index acef17c..0000000 --- a/templates/settings.tpl +++ /dev/null @@ -1,45 +0,0 @@ - false, - - // Enable debug mode (to print errors). - 'debug' => true, - - 'sp' => array ( - 'entityId' => '{{sp_base}}/metadata.php', - 'assertionConsumerService' => array ( - 'url' => '{{sp_base}}/index.php?acs', - ), - 'singleLogoutService' => array ( - 'url' => '{{sp_base}}/index.php?sls', - ), - 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient', - 'x509cert' => '{{sp_cert}}', - 'privateKey' => '{{sp_key}}', - ), - 'idp' => array ( - 'entityId' => '{{idp_entityid}}', - 'singleSignOnService' => array ( - 'url' => '{{idp_sso}}', - ), - 'singleLogoutService' => array ( - 'url' => '{{idp_slo}}', - ), - 'x509cert' => '{{idp_cert}}', - ), - 'security' => array ( - 'authnRequestsSigned' => true, - 'logoutRequestSigned' => true, - 'logoutResponseSigned' => true, - 'signMetadata' => true, - 'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', - 'requestedAuthnContext' => array('https://www.spid.gov.it/SpidL1'), - ), - ); diff --git a/www/attrs.php b/www/attrs.php deleted file mode 100644 index 9905e61..0000000 --- a/www/attrs.php +++ /dev/null @@ -1,25 +0,0 @@ -'; - echo ''; - foreach ($attributes as $attributeName => $attributeValues) { - echo ''; - } - echo '
NameValues
' . htmlentities($attributeName) . '
    '; - foreach ($attributeValues as $attributeValue) { - echo '
  • ' . htmlentities($attributeValue) . '
  • '; - } - echo '
'; - } else { - echo "

You don't have any attribute

"; - } - - echo '

Logout

'; -} else { - echo '

Login and access later to this page

'; -} diff --git a/www/index.php b/www/index.php deleted file mode 100644 index 4b1d796..0000000 --- a/www/index.php +++ /dev/null @@ -1,123 +0,0 @@ -login(); - - # If AuthNRequest ID need to be saved in order to later validate it, do instead - # $ssoBuiltUrl = $auth->login(null, array(), false, false, true); - # $_SESSION['AuthNRequestID'] = $auth->getLastRequestID(); - # header('Pragma: no-cache'); - # header('Cache-Control: no-cache, must-revalidate'); - # header('Location: ' . $ssoBuiltUrl); - # exit(); -} elseif (isset($_GET['sso2'])) { - $returnTo = $spBaseUrl . '/attrs.php'; - $auth->login($returnTo); -} elseif (isset($_GET['slo'])) { - $returnTo = null; - $parameters = array(); - $nameId = null; - $sessionIndex = null; - $nameIdFormat = null; - - if (isset($_SESSION['samlNameId'])) { - $nameId = $_SESSION['samlNameId']; - } - if (isset($_SESSION['samlSessionIndex'])) { - $sessionIndex = $_SESSION['samlSessionIndex']; - } - if (isset($_SESSION['samlNameIdFormat'])) { - $nameIdFormat = $_SESSION['samlNameIdFormat']; - } - - $auth->logout($returnTo, $parameters, $nameId, $sessionIndex, false, $nameIdFormat, 'aaa'); - - # If LogoutRequest ID need to be saved in order to later validate it, do instead - # $sloBuiltUrl = $auth->logout(null, $parameters, $nameId, $sessionIndex, true); - # $_SESSION['LogoutRequestID'] = $auth->getLastRequestID(); - # header('Pragma: no-cache'); - # header('Cache-Control: no-cache, must-revalidate'); - # header('Location: ' . $sloBuiltUrl); - # exit(); -} elseif (isset($_GET['acs'])) { - if (isset($_SESSION) && isset($_SESSION['AuthNRequestID'])) { - $requestID = $_SESSION['AuthNRequestID']; - } else { - $requestID = null; - } - - $auth->processResponse($requestID); - - $errors = $auth->getErrors(); - - if (!empty($errors)) { - echo '

' . implode(', ', $errors) . '

'; - } - - if (!$auth->isAuthenticated()) { - echo '

Not authenticated

'; - exit(); - } - - $_SESSION['samlUserdata'] = $auth->getAttributes(); - $_SESSION['samlNameId'] = $auth->getNameId(); - $_SESSION['samlNameIdFormat'] = $auth->getNameIdFormat(); - $_SESSION['samlSessionIndex'] = $auth->getSessionIndex(); - unset($_SESSION['AuthNRequestID']); - if (isset($_POST['RelayState']) && Utils::getSelfURL() != $_POST['RelayState']) { - $auth->redirectTo($_POST['RelayState']); - } -} elseif (isset($_GET['sls'])) { - if (isset($_SESSION) && isset($_SESSION['LogoutRequestID'])) { - $requestID = $_SESSION['LogoutRequestID']; - } else { - $requestID = null; - } - - $auth->processSLO(false, $requestID); - $errors = $auth->getErrors(); - if (empty($errors)) { - echo '

Sucessfully logged out

'; - } else { - echo '

' . implode(', ', $errors) . '

'; - } -} - -if (isset($_SESSION['samlUserdata'])) { - if (!empty($_SESSION['samlUserdata'])) { - $attributes = $_SESSION['samlUserdata']; - echo 'You have the following attributes:
'; - echo ''; - foreach ($attributes as $attributeName => $attributeValues) { - echo ''; - } - echo '
NameValues
' . htmlentities($attributeName) . '
    '; - foreach ($attributeValues as $attributeValue) { - echo '
  • ' . htmlentities($attributeValue) . '
  • '; - } - echo '
'; - } else { - echo "

You don't have any attribute

"; - } - - echo '

Logout

'; -} else { - echo '

Login

'; - echo '

Login and access to attrs.php page

'; - echo '

Show the SP metadata

'; -} diff --git a/www/metadata.php b/www/metadata.php deleted file mode 100644 index 0500dee..0000000 --- a/www/metadata.php +++ /dev/null @@ -1,32 +0,0 @@ -getSettings(); - // Now we only validate SP settings - $settings = new Settings($settingsInfo, true); - $metadata = $settings->getSPMetadata(); - $errors = $settings->validateMetadata($metadata); - if (empty($errors)) { - header('Content-Type: text/xml'); - echo $metadata; - } else { - throw new Error( - 'Invalid SP metadata: '.implode(', ', $errors), - Error::METADATA_SP_INVALID - ); - } -} catch (Exception $e) { - echo $e->getMessage(); -} diff --git a/www2/attrs.php b/www2/attrs.php deleted file mode 100644 index 9905e61..0000000 --- a/www2/attrs.php +++ /dev/null @@ -1,25 +0,0 @@ -'; - echo ''; - foreach ($attributes as $attributeName => $attributeValues) { - echo ''; - } - echo '
NameValues
' . htmlentities($attributeName) . '
    '; - foreach ($attributeValues as $attributeValue) { - echo '
  • ' . htmlentities($attributeValue) . '
  • '; - } - echo '
'; - } else { - echo "

You don't have any attribute

"; - } - - echo '

Logout

'; -} else { - echo '

Login and access later to this page

'; -} diff --git a/www2/index.php b/www2/index.php deleted file mode 100644 index b87ad3a..0000000 --- a/www2/index.php +++ /dev/null @@ -1,119 +0,0 @@ -login(); - - # If AuthNRequest ID need to be saved in order to later validate it, do instead - # $ssoBuiltUrl = $auth->login(null, array(), false, false, true); - # $_SESSION['AuthNRequestID'] = $auth->getLastRequestID(); - # header('Pragma: no-cache'); - # header('Cache-Control: no-cache, must-revalidate'); - # header('Location: ' . $ssoBuiltUrl); - # exit(); -} elseif (isset($_GET['sso2'])) { - $returnTo = $spBaseUrl . '/attrs.php'; - $auth->login($returnTo); -} elseif (isset($_GET['slo'])) { - $returnTo = null; - $parameters = array(); - $nameId = null; - $sessionIndex = null; - $nameIdFormat = null; - - if (isset($_SESSION['samlNameId'])) { - $nameId = $_SESSION['samlNameId']; - } - if (isset($_SESSION['samlSessionIndex'])) { - $sessionIndex = $_SESSION['samlSessionIndex']; - } - if (isset($_SESSION['samlNameIdFormat'])) { - $nameIdFormat = $_SESSION['samlNameIdFormat']; - } - - $auth->logout($returnTo, $parameters, $nameId, $sessionIndex, false, $nameIdFormat); - - # If LogoutRequest ID need to be saved in order to later validate it, do instead - # $sloBuiltUrl = $auth->logout(null, $parameters, $nameId, $sessionIndex, true); - # $_SESSION['LogoutRequestID'] = $auth->getLastRequestID(); - # header('Pragma: no-cache'); - # header('Cache-Control: no-cache, must-revalidate'); - # header('Location: ' . $sloBuiltUrl); - # exit(); -} elseif (isset($_GET['acs'])) { - if (isset($_SESSION) && isset($_SESSION['AuthNRequestID'])) { - $requestID = $_SESSION['AuthNRequestID']; - } else { - $requestID = null; - } - - $auth->processResponse($requestID); - - $errors = $auth->getErrors(); - - if (!empty($errors)) { - echo '

' . implode(', ', $errors) . '

'; - } - - if (!$auth->isAuthenticated()) { - echo '

Not authenticated

'; - exit(); - } - - $_SESSION['samlUserdata'] = $auth->getAttributes(); - $_SESSION['samlNameId'] = $auth->getNameId(); - $_SESSION['samlNameIdFormat'] = $auth->getNameIdFormat(); - $_SESSION['samlSessionIndex'] = $auth->getSessionIndex(); - unset($_SESSION['AuthNRequestID']); - if (isset($_POST['RelayState']) && OneLogin_Saml2_Utils::getSelfURL() != $_POST['RelayState']) { - $auth->redirectTo($_POST['RelayState']); - } -} elseif (isset($_GET['sls'])) { - if (isset($_SESSION) && isset($_SESSION['LogoutRequestID'])) { - $requestID = $_SESSION['LogoutRequestID']; - } else { - $requestID = null; - } - - $auth->processSLO(false, $requestID); - $errors = $auth->getErrors(); - if (empty($errors)) { - echo '

Sucessfully logged out

'; - } else { - echo '

' . implode(', ', $errors) . '

'; - } -} - -if (isset($_SESSION['samlUserdata'])) { - if (!empty($_SESSION['samlUserdata'])) { - $attributes = $_SESSION['samlUserdata']; - echo 'You have the following attributes:
'; - echo ''; - foreach ($attributes as $attributeName => $attributeValues) { - echo ''; - } - echo '
NameValues
' . htmlentities($attributeName) . '
    '; - foreach ($attributeValues as $attributeValue) { - echo '
  • ' . htmlentities($attributeValue) . '
  • '; - } - echo '
'; - } else { - echo "

You don't have any attribute

"; - } - - echo '

Logout

'; -} else { - echo '

Login

'; - echo '

Login and access to attrs.php page

'; - echo '

Show the SP metadata

'; -} diff --git a/www2/metadata.php b/www2/metadata.php deleted file mode 100644 index 7f00b44..0000000 --- a/www2/metadata.php +++ /dev/null @@ -1,29 +0,0 @@ -getSettings(); - // Now we only validate SP settings - $settings = new OneLogin_Saml2_Settings($settingsInfo, true); - $metadata = $settings->getSPMetadata(); - $errors = $settings->validateMetadata($metadata); - if (empty($errors)) { - header('Content-Type: text/xml'); - echo $metadata; - } else { - throw new OneLogin_Saml2_Error( - 'Invalid SP metadata: '.implode(', ', $errors), - OneLogin_Saml2_Error::METADATA_SP_INVALID - ); - } -} catch (Exception $e) { - echo $e->getMessage(); -} diff --git a/xenc-schema.xsd b/xenc-schema.xsd deleted file mode 100644 index dd85887..0000000 --- a/xenc-schema.xsd +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - ]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/xml.xsd b/xml.xsd deleted file mode 100644 index aea7d0d..0000000 --- a/xml.xsd +++ /dev/null @@ -1,287 +0,0 @@ - - - - - - -
-

About the XML namespace

- -
-

- This schema document describes the XML namespace, in a form - suitable for import by other schema documents. -

-

- See - http://www.w3.org/XML/1998/namespace.html and - - http://www.w3.org/TR/REC-xml for information - about this namespace. -

-

- Note that local names in this namespace are intended to be - defined only by the World Wide Web Consortium or its subgroups. - The names currently defined in this namespace are listed below. - They should not be used with conflicting semantics by any Working - Group, specification, or document instance. -

-

- See further below in this document for more information about how to refer to this schema document from your own - XSD schema documents and about the - namespace-versioning policy governing this schema document. -

-
-
-
-
- - - - -
- -

lang (as an attribute name)

-

- denotes an attribute whose value - is a language code for the natural language of the content of - any element; its value is inherited. This name is reserved - by virtue of its definition in the XML specification.

- -
-
-

Notes

-

- Attempting to install the relevant ISO 2- and 3-letter - codes as the enumerated possible values is probably never - going to be a realistic possibility. -

-

- See BCP 47 at - http://www.rfc-editor.org/rfc/bcp/bcp47.txt - and the IANA language subtag registry at - - http://www.iana.org/assignments/language-subtag-registry - for further information. -

-

- The union allows for the 'un-declaration' of xml:lang with - the empty string. -

-
-
-
- - - - - - - - - -
- - - - -
- -

space (as an attribute name)

-

- denotes an attribute whose - value is a keyword indicating what whitespace processing - discipline is intended for the content of the element; its - value is inherited. This name is reserved by virtue of its - definition in the XML specification.

- -
-
-
- - - - - - -
- - - -
- -

base (as an attribute name)

-

- denotes an attribute whose value - provides a URI to be used as the base for interpreting any - relative URIs in the scope of the element on which it - appears; its value is inherited. This name is reserved - by virtue of its definition in the XML Base specification.

- -

- See http://www.w3.org/TR/xmlbase/ - for information about this attribute. -

-
-
-
-
- - - - -
- -

id (as an attribute name)

-

- denotes an attribute whose value - should be interpreted as if declared to be of type ID. - This name is reserved by virtue of its definition in the - xml:id specification.

- -

- See http://www.w3.org/TR/xml-id/ - for information about this attribute. -

-
-
-
-
- - - - - - - - - - -
- -

Father (in any context at all)

- -
-

- denotes Jon Bosak, the chair of - the original XML Working Group. This name is reserved by - the following decision of the W3C XML Plenary and - XML Coordination groups: -

-
-

- In appreciation for his vision, leadership and - dedication the W3C XML Plenary on this 10th day of - February, 2000, reserves for Jon Bosak in perpetuity - the XML name "xml:Father". -

-
-
-
-
-
- - - -
-

About this schema document

- -
-

- This schema defines attributes and an attribute group suitable - for use by schemas wishing to allow xml:base, - xml:lang, xml:space or - xml:id attributes on elements they define. -

-

- To enable this, such a schema must import this schema for - the XML namespace, e.g. as follows: -

-
-          <schema . . .>
-           . . .
-           <import namespace="http://www.w3.org/XML/1998/namespace"
-                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
-     
-

- or -

-
-           <import namespace="http://www.w3.org/XML/1998/namespace"
-                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
-     
-

- Subsequently, qualified reference to any of the attributes or the - group defined below will have the desired effect, e.g. -

-
-          <type . . .>
-           . . .
-           <attributeGroup ref="xml:specialAttrs"/>
-     
-

- will define a type which will schema-validate an instance element - with any of those attributes. -

-
-
-
-
- - - -
-

Versioning policy for this schema document

-
-

- In keeping with the XML Schema WG's standard versioning - policy, this schema document will persist at - - http://www.w3.org/2009/01/xml.xsd. -

-

- At the date of issue it can also be found at - - http://www.w3.org/2001/xml.xsd. -

-

- The schema document at that URI may however change in the future, - in order to remain compatible with the latest version of XML - Schema itself, or with the XML namespace itself. In other words, - if the XML Schema or XML namespaces change, the version of this - document at - http://www.w3.org/2001/xml.xsd - - will change accordingly; the version at - - http://www.w3.org/2009/01/xml.xsd - - will not change. -

-

- Previous dated (and unchanging) versions of this schema - document are at: -

- -
-
-
-
- -
- diff --git a/xmldsig-core-schema.xsd b/xmldsig-core-schema.xsd deleted file mode 100644 index df126b3..0000000 --- a/xmldsig-core-schema.xsd +++ /dev/null @@ -1,318 +0,0 @@ - - - - - - ]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -