From 7787f08768ad18990b55c10d5864d61434cf03c0 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 20 Jul 2018 11:10:54 +0200
Subject: [PATCH 01/69] added base class wrapper files
---
src/PhpSaml.php | 18 ++++++++++++++
src/PhpSamlInterface.php | 0
src/config/saml_config.php | 48 ++++++++++++++++++++++++++++++++++++
src/saml/PhpSamlOneLogin.php | 5 ++++
www3/index.php | 0
5 files changed, 71 insertions(+)
create mode 100644 src/PhpSaml.php
create mode 100644 src/PhpSamlInterface.php
create mode 100644 src/config/saml_config.php
create mode 100644 src/saml/PhpSamlOneLogin.php
create mode 100644 www3/index.php
diff --git a/src/PhpSaml.php b/src/PhpSaml.php
new file mode 100644
index 0000000..5ee4fe9
--- /dev/null
+++ b/src/PhpSaml.php
@@ -0,0 +1,18 @@
+php_saml = new PhpSamlOneLogin($settings);
+ break;
+ default:
+ $this->php_saml = new PhpSamlOneLogin($settings);
+ break;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/PhpSamlInterface.php b/src/PhpSamlInterface.php
new file mode 100644
index 0000000..e69de29
diff --git a/src/config/saml_config.php b/src/config/saml_config.php
new file mode 100644
index 0000000..a91e5fe
--- /dev/null
+++ b/src/config/saml_config.php
@@ -0,0 +1,48 @@
+ false,
+
+ // Enable debug mode (to print errors).
+ 'debug' => true,
+
+ 'sp' => array (
+ 'entityId' => $spBaseUrl . '/metadata.php',
+ 'assertionConsumerService' => array (
+ 'url' => $spBaseUrl . '/index.php?acs',
+ ),
+ 'singleLogoutService' => array (
+ 'url' => $spBaseUrl . '/index.php?sls',
+ ),
+ 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
+ 'x509cert' => '{{sp_cert}}',
+ 'privateKey' => '{{sp_key}}',
+ ),
+ 'idp' => array (
+ 'entityId' => $idpEntityId,
+ 'singleSignOnService' => array (
+ 'url' => $idpSSO,
+ ),
+ 'singleLogoutService' => array (
+ 'url' => $idpSLO,
+ ),
+ '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/src/saml/PhpSamlOneLogin.php b/src/saml/PhpSamlOneLogin.php
new file mode 100644
index 0000000..d22b697
--- /dev/null
+++ b/src/saml/PhpSamlOneLogin.php
@@ -0,0 +1,5 @@
+
Date: Fri, 20 Jul 2018 12:07:49 +0200
Subject: [PATCH 02/69] added default config and strategy pattern
---
src/PhpSaml.php | 4 +--
src/PhpSamlInterface.php | 0
...ml_config.php => onelogin_saml_config.php} | 14 ++++++---
src/saml/PhpSamlOneLogin.php | 5 ---
src/saml_strategy/PhpSamlInterface.php | 7 +++++
src/saml_strategy/PhpSamlOneLogin.php | 31 +++++++++++++++++++
www3/index.php | 11 +++++++
7 files changed, 60 insertions(+), 12 deletions(-)
delete mode 100644 src/PhpSamlInterface.php
rename src/config/{saml_config.php => onelogin_saml_config.php} (85%)
delete mode 100644 src/saml/PhpSamlOneLogin.php
create mode 100644 src/saml_strategy/PhpSamlInterface.php
create mode 100644 src/saml_strategy/PhpSamlOneLogin.php
diff --git a/src/PhpSaml.php b/src/PhpSaml.php
index 5ee4fe9..6d5835b 100644
--- a/src/PhpSaml.php
+++ b/src/PhpSaml.php
@@ -4,8 +4,8 @@ class PhpSaml implements PhpSamlInterface {
private $php_saml = null;
- public function __construct($settings, $mode = 'onelogin') {
- switch ($variable) {
+ public function __construct($settings = null, $mode = 'onelogin') {
+ switch ($mode) {
case 'onelogin':
$this->php_saml = new PhpSamlOneLogin($settings);
break;
diff --git a/src/PhpSamlInterface.php b/src/PhpSamlInterface.php
deleted file mode 100644
index e69de29..0000000
diff --git a/src/config/saml_config.php b/src/config/onelogin_saml_config.php
similarity index 85%
rename from src/config/saml_config.php
rename to src/config/onelogin_saml_config.php
index a91e5fe..bbd1bbd 100644
--- a/src/config/saml_config.php
+++ b/src/config/onelogin_saml_config.php
@@ -1,11 +1,15 @@
$spBaseUrl . '/index.php?sls',
),
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
- 'x509cert' => '{{sp_cert}}',
- 'privateKey' => '{{sp_key}}',
+ 'x509cert' => $spCrtFile,
+ 'privateKey' => $spKeyFile,
),
'idp' => array (
'entityId' => $idpEntityId,
@@ -35,7 +39,7 @@
'singleLogoutService' => array (
'url' => $idpSLO,
),
- 'x509cert' => '{{idp_cert}}',
+ 'x509cert' => $idpCertFile,
),
'security' => array (
'authnRequestsSigned' => true,
diff --git a/src/saml/PhpSamlOneLogin.php b/src/saml/PhpSamlOneLogin.php
deleted file mode 100644
index d22b697..0000000
--- a/src/saml/PhpSamlOneLogin.php
+++ /dev/null
@@ -1,5 +0,0 @@
-init($settings);
+ print_r($this->settings);
+ }
+
+ function init($settings)
+ {
+ require_once(__DIR__ . '/../config/onelogin_saml_config.php');
+ $this->settings = is_null($settings) ? $defaultSettings : array_merge($defaultSettings, $settings);
+ }
+
+ function login()
+ {
+
+ }
+
+ function logout()
+ {
+
+ }
+
+}
\ No newline at end of file
diff --git a/www3/index.php b/www3/index.php
index e69de29..963f930 100644
--- a/www3/index.php
+++ b/www3/index.php
@@ -0,0 +1,11 @@
+
Date: Fri, 20 Jul 2018 12:40:54 +0200
Subject: [PATCH 03/69] implemented login
---
src/PhpSaml.php | 7 +-
src/saml_strategy/PhpSamlOneLogin.php | 116 +++++++++++++++++++++++++-
2 files changed, 120 insertions(+), 3 deletions(-)
diff --git a/src/PhpSaml.php b/src/PhpSaml.php
index 6d5835b..7b719f8 100644
--- a/src/PhpSaml.php
+++ b/src/PhpSaml.php
@@ -1,10 +1,15 @@
php_saml = new PhpSamlOneLogin($settings);
diff --git a/src/saml_strategy/PhpSamlOneLogin.php b/src/saml_strategy/PhpSamlOneLogin.php
index c2164e2..0ce618b 100644
--- a/src/saml_strategy/PhpSamlOneLogin.php
+++ b/src/saml_strategy/PhpSamlOneLogin.php
@@ -1,10 +1,13 @@
settings);
}
- function init($settings)
+ private function init($settings)
{
require_once(__DIR__ . '/../config/onelogin_saml_config.php');
$this->settings = is_null($settings) ? $defaultSettings : array_merge($defaultSettings, $settings);
+ $auth = new OneLogin_Saml2_Auth($this->settings);
}
function login()
{
+ if ( $auth->isAuthenticated ) {
+ return;
+ }
+ $auth->login();
+ $requestID = null;
+ if (isset($_SESSION['AuthNRequestID'])) {
+ $requestID = $_SESSION['AuthNRequestID'];
+ }
+
+ $auth->processResponse($requestID);
+ unset($_SESSION['AuthNRequestID']);
+
+ $errors = $auth->getErrors();
+ if (!empty($errors)) {
+ return $errors;
+ }
+
+ if (!$auth->isAuthenticated()) {
+ return false;
+ }
+
+ $_SESSION['samlUserdata'] = $auth->getAttributes();
+ $_SESSION['samlNameId'] = $auth->getNameId();
+ $_SESSION['samlNameIdFormat'] = $auth->getNameIdFormat();
+ $_SESSION['samlSessionIndex'] = $auth->getSessionIndex();
+
+ if (isset($_POST['RelayState']) && OneLogin_Saml2_Utils::getSelfURL() != $_POST['RelayState']) {
+ $auth->redirectTo($_POST['RelayState']);
+ }
+
+ $attributes = $_SESSION['samlUserdata'];
+ $nameId = $_SESSION['samlNameId'];
+
+ echo 'Identified user: '. htmlentities($nameId) .'
';
+
+ if (!empty($attributes)) {
+ echo ''._('User attributes:').'
';
+ echo ''._('Name').' | '._('Values').' | ';
+ foreach ($attributes as $attributeName => $attributeValues) {
+ echo '' . htmlentities($attributeName) . ' | ';
+ foreach ($attributeValues as $attributeValue) {
+ echo '- ' . htmlentities($attributeValue) . '
';
+ }
+ echo ' |
';
+ }
+ echo '
';
+ } else {
+ echo _('No attributes found.');
+ }
}
function logout()
- {
+ {
+ if (isset($_GET['sso'])) { // SSO action. Will send an AuthNRequest to the IdP
+ $auth->login();
+ } else if (isset($_GET['sso2'])) { // Another SSO action
+ $returnTo = $spBaseUrl.'/demo1/attrs.php'; // but set a custom RelayState URL
+ $auth->login($returnTo);
+ } else if (isset($_GET['slo'])) { // SLO action. Will sent a Logout Request to IdP
+ $auth->logout();
+ } else if (isset($_GET['acs'])) { // Assertion Consumer Service
+ $auth->processResponse(); // Process the Response of the IdP, get the
+ // attributes and put then at
+ // $_SESSION['samlUserdata']
+
+ $errors = $auth->getErrors(); // This method receives an array with the errors
+ // that could took place during the process
+
+ if (!empty($errors)) {
+ echo '', implode(', ', $errors), '
';
+ }
+ // This check if the response was
+ if (!$auth->isAuthenticated()) { // sucessfully validated and the user
+ echo "Not authenticated
"; // data retrieved or not
+ exit();
+ }
+
+ $_SESSION['samlUserdata'] = $auth->getAttributes(); // Retrieves user data
+ if (isset($_POST['RelayState']) && OneLogin_Saml2_Utils::getSelfURL() != $_POST['RelayState']) {
+ $auth->redirectTo($_POST['RelayState']); // Redirect if there is a
+ } // relayState set
+ } else if (isset($_GET['sls'])) { // Single Logout Service
+ $auth->processSLO(); // Process the Logout Request & Logout Response
+ $errors = $auth->getErrors(); // Retrieves possible validation errors
+ if (empty($errors)) {
+ echo 'Sucessfully logged out
';
+ } else {
+ echo '', implode(', ', $errors), '
';
+ }
+ }
+
+ if (isset($_SESSION['samlUserdata'])) { // If there is user data we print it.
+ if (!empty($_SESSION['samlUserdata'])) {
+ $attributes = $_SESSION['samlUserdata'];
+ echo 'You have the following attributes:
';
+ echo 'Name | Values | ';
+ foreach ($attributes as $attributeName => $attributeValues) {
+ echo '' . htmlentities($attributeName) . ' | ';
+ foreach ($attributeValues as $attributeValue) {
+ echo '- ' . htmlentities($attributeValue) . '
';
+ }
+ echo ' |
';
+ }
+ echo '
';
+ } else { // If there is not user data, we notify
+ echo "You don't have any attribute
";
+ }
+ echo 'Logout
'; // Print some links with possible
+ } else { // actions
+ echo 'Login
';
+ echo 'Login and access to attrs.php page
';
+ }
}
}
\ No newline at end of file
From a5fe8ce397e6e653fc8a25b5c6756172241cdbb3 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 20 Jul 2018 12:45:21 +0200
Subject: [PATCH 04/69] implemented logout
---
src/saml_strategy/PhpSamlOneLogin.php | 90 ++++-----------------------
1 file changed, 12 insertions(+), 78 deletions(-)
diff --git a/src/saml_strategy/PhpSamlOneLogin.php b/src/saml_strategy/PhpSamlOneLogin.php
index 0ce618b..b032b63 100644
--- a/src/saml_strategy/PhpSamlOneLogin.php
+++ b/src/saml_strategy/PhpSamlOneLogin.php
@@ -24,8 +24,8 @@ private function init($settings)
function login()
{
- if ( $auth->isAuthenticated ) {
- return;
+ if ($auth->isAuthenticated) {
+ return false;
}
$auth->login();
@@ -51,93 +51,27 @@ function login()
$_SESSION['samlNameIdFormat'] = $auth->getNameIdFormat();
$_SESSION['samlSessionIndex'] = $auth->getSessionIndex();
- if (isset($_POST['RelayState']) && OneLogin_Saml2_Utils::getSelfURL() != $_POST['RelayState']) {
- $auth->redirectTo($_POST['RelayState']);
+ if (!empty($_SESSION['samlUserdata'])) {
+ return true;
}
- $attributes = $_SESSION['samlUserdata'];
- $nameId = $_SESSION['samlNameId'];
-
- echo 'Identified user: '. htmlentities($nameId) .'
';
-
- if (!empty($attributes)) {
- echo ''._('User attributes:').'
';
- echo ''._('Name').' | '._('Values').' | ';
- foreach ($attributes as $attributeName => $attributeValues) {
- echo '' . htmlentities($attributeName) . ' | ';
- foreach ($attributeValues as $attributeValue) {
- echo '- ' . htmlentities($attributeValue) . '
';
- }
- echo ' |
';
- }
- echo '
';
- } else {
- echo _('No attributes found.');
- }
+ return false;
}
function logout()
{
- if (isset($_GET['sso'])) { // SSO action. Will send an AuthNRequest to the IdP
- $auth->login();
- } else if (isset($_GET['sso2'])) { // Another SSO action
- $returnTo = $spBaseUrl.'/demo1/attrs.php'; // but set a custom RelayState URL
- $auth->login($returnTo);
- } else if (isset($_GET['slo'])) { // SLO action. Will sent a Logout Request to IdP
+ if (!$auth->isAuthenticated()) {
+ return false;
+ }
$auth->logout();
- } else if (isset($_GET['acs'])) { // Assertion Consumer Service
- $auth->processResponse(); // Process the Response of the IdP, get the
- // attributes and put then at
- // $_SESSION['samlUserdata']
-
- $errors = $auth->getErrors(); // This method receives an array with the errors
- // that could took place during the process
+ $auth->processSLO();
+ $errors = $auth->getErrors();
if (!empty($errors)) {
- echo '', implode(', ', $errors), '
';
- }
- // This check if the response was
- if (!$auth->isAuthenticated()) { // sucessfully validated and the user
- echo "Not authenticated
"; // data retrieved or not
- exit();
- }
-
- $_SESSION['samlUserdata'] = $auth->getAttributes(); // Retrieves user data
- if (isset($_POST['RelayState']) && OneLogin_Saml2_Utils::getSelfURL() != $_POST['RelayState']) {
- $auth->redirectTo($_POST['RelayState']); // Redirect if there is a
- } // relayState set
- } else if (isset($_GET['sls'])) { // Single Logout Service
- $auth->processSLO(); // Process the Logout Request & Logout Response
- $errors = $auth->getErrors(); // Retrieves possible validation errors
- if (empty($errors)) {
- echo 'Sucessfully logged out
';
- } else {
- echo '', implode(', ', $errors), '
';
- }
- }
-
- if (isset($_SESSION['samlUserdata'])) { // If there is user data we print it.
- if (!empty($_SESSION['samlUserdata'])) {
- $attributes = $_SESSION['samlUserdata'];
- echo 'You have the following attributes:
';
- echo 'Name | Values | ';
- foreach ($attributes as $attributeName => $attributeValues) {
- echo '' . htmlentities($attributeName) . ' | ';
- foreach ($attributeValues as $attributeValue) {
- echo '- ' . htmlentities($attributeValue) . '
';
- }
- echo ' |
';
- }
- echo '
';
- } else { // If there is not user data, we notify
- echo "You don't have any attribute
";
+ return $errors;
}
- echo 'Logout
'; // Print some links with possible
- } else { // actions
- echo 'Login
';
- echo 'Login and access to attrs.php page
';
- }
+ return true;
}
}
\ No newline at end of file
From 4095b4374fa050f83bec546fad113bae398d6274 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 20 Jul 2018 14:41:34 +0200
Subject: [PATCH 05/69] added settings validation
---
...saml_config.php => OneloginSamlConfig.php} | 0
src/helper/ArrayHelper.php | 20 +++++++++++++++++++
src/saml_strategy/PhpSamlOneLogin.php | 20 +++++++++++++++----
3 files changed, 36 insertions(+), 4 deletions(-)
rename src/config/{onelogin_saml_config.php => OneloginSamlConfig.php} (100%)
create mode 100644 src/helper/ArrayHelper.php
diff --git a/src/config/onelogin_saml_config.php b/src/config/OneloginSamlConfig.php
similarity index 100%
rename from src/config/onelogin_saml_config.php
rename to src/config/OneloginSamlConfig.php
diff --git a/src/helper/ArrayHelper.php b/src/helper/ArrayHelper.php
new file mode 100644
index 0000000..17812f1
--- /dev/null
+++ b/src/helper/ArrayHelper.php
@@ -0,0 +1,20 @@
+ $v) {
+ if (is_array($arr1[$k]) && is_array($arr2[$k])) {
+ $d = array_diff_key_recursive($arr1[$k], $arr2[$k]);
+
+ if ($d) {
+ $diff[$k] = $d;
+ }
+ }
+ }
+
+ return $diff;
+}
+
+?>
\ No newline at end of file
diff --git a/src/saml_strategy/PhpSamlOneLogin.php b/src/saml_strategy/PhpSamlOneLogin.php
index b032b63..229c67a 100644
--- a/src/saml_strategy/PhpSamlOneLogin.php
+++ b/src/saml_strategy/PhpSamlOneLogin.php
@@ -1,5 +1,6 @@
settings = is_null($settings) ? $defaultSettings : array_merge($defaultSettings, $settings);
+ require_once(__DIR__ . '/../config/OneloginSamlConfig.php');
+ if (!is_null($settings)) {
+ $diff = array_diff_key_recursive($settings, $defaultSettings);
+ if (!empty($diff)) {
+ $message = "The following keys are invalid for settings array: ";
+ array_walk_recursive($diff, function($v, $k) {
+ $message .= $k . ", ";
+ });
+ throw new Exception($message, 1);
+ }
+ }
+ $this->settings = is_null($settings) ? $defaultSettings : array_merge_recursive($defaultSettings, $settings);
+
$auth = new OneLogin_Saml2_Auth($this->settings);
}
- function login()
+ public function login()
{
if ($auth->isAuthenticated) {
return false;
@@ -58,7 +70,7 @@ function login()
return false;
}
- function logout()
+ public function logout()
{
if (!$auth->isAuthenticated()) {
return false;
From 61cdee19baa21ce305e44150844fb360f486276d Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 20 Jul 2018 16:20:11 +0200
Subject: [PATCH 06/69] code cleanup and added settings management class
---
bin/Configuration.php | 8 ++
composer.json | 12 +++
src/PhpSaml.php | 10 ++-
src/config/OneloginSamlConfig.php | 106 +++++++++++++----------
src/helper/ArrayHelper.php | 30 ++++---
src/helper/IdpHelper.php | 36 ++++++++
src/saml_strategy/PhpSamlOneLogin.php | 39 +++++----
templates/settings.tpl | 45 ----------
www/attrs.php | 25 ------
www/index.php | 116 +------------------------
www/metadata.php | 32 -------
www2/attrs.php | 25 ------
www2/index.php | 119 --------------------------
www2/metadata.php | 29 -------
www3/index.php | 11 ---
15 files changed, 167 insertions(+), 476 deletions(-)
create mode 100644 bin/Configuration.php
create mode 100644 src/helper/IdpHelper.php
delete mode 100644 templates/settings.tpl
delete mode 100644 www/attrs.php
delete mode 100644 www/metadata.php
delete mode 100644 www2/attrs.php
delete mode 100644 www2/index.php
delete mode 100644 www2/metadata.php
delete mode 100644 www3/index.php
diff --git a/bin/Configuration.php b/bin/Configuration.php
new file mode 100644
index 0000000..58e43de
--- /dev/null
+++ b/bin/Configuration.php
@@ -0,0 +1,8 @@
+php_saml = new PhpSamlOneLogin($settings);
+ $this->php_saml = new PhpSamlOneLogin($idpUrl, $settings);
break;
default:
- $this->php_saml = new PhpSamlOneLogin($settings);
+ $this->php_saml = new PhpSamlOneLogin($idpUrl, $settings);
break;
}
}
diff --git a/src/config/OneloginSamlConfig.php b/src/config/OneloginSamlConfig.php
index bbd1bbd..1f76a2a 100644
--- a/src/config/OneloginSamlConfig.php
+++ b/src/config/OneloginSamlConfig.php
@@ -1,52 +1,72 @@
false,
+ function __construct()
+ {
+ $this->spAcsUrl = $this->spBaseUrl . '/index.php?acs';
+ $this->spSloUrl = $this->spBaseUrl . '/index.php?sls';
+ $this->idpSSO = $this->idpEntityId . '/sso';
+ $this->idpSLO = $this->idpEntityId . '/slo';
+ }
- // Enable debug mode (to print errors).
- 'debug' => true,
+ public function getSettings()
+ {
+ return $defaultSettings = 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' => false,
+
+ // Enable debug mode (to print errors).
+ 'debug' => true,
- 'sp' => array (
- 'entityId' => $spBaseUrl . '/metadata.php',
- 'assertionConsumerService' => array (
- 'url' => $spBaseUrl . '/index.php?acs',
+ 'sp' => array(
+ 'entityId' => $spBaseUrl . '/metadata.php',
+ 'assertionConsumerService' => array(
+ 'url' => $spAcsUrl,
+ ),
+ 'singleLogoutService' => array(
+ 'url' => $spSloUrl,
+ ),
+ 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
+ 'x509cert' => $spCrtFile,
+ 'privateKey' => $spKeyFile,
),
- 'singleLogoutService' => array (
- 'url' => $spBaseUrl . '/index.php?sls',
+ 'idp' => array(
+ 'entityId' => $idpEntityId,
+ 'singleSignOnService' => array(
+ 'url' => $idpSSO,
+ ),
+ 'singleLogoutService' => array(
+ 'url' => $idpSLO,
+ ),
+ 'x509cert' => $idpCertFile,
),
- 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
- 'x509cert' => $spCrtFile,
- 'privateKey' => $spKeyFile,
- ),
- 'idp' => array (
- 'entityId' => $idpEntityId,
- 'singleSignOnService' => array (
- 'url' => $idpSSO,
+ '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'),
),
- 'singleLogoutService' => array (
- 'url' => $idpSLO,
- ),
- 'x509cert' => $idpCertFile,
- ),
- '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'),
- ),
- );
+ );
+ }
+
+ public function updateSettings($settings) {
+
+ }
+}
\ No newline at end of file
diff --git a/src/helper/ArrayHelper.php b/src/helper/ArrayHelper.php
index 17812f1..7737567 100644
--- a/src/helper/ArrayHelper.php
+++ b/src/helper/ArrayHelper.php
@@ -1,20 +1,22 @@
$v) {
- if (is_array($arr1[$k]) && is_array($arr2[$k])) {
- $d = array_diff_key_recursive($arr1[$k], $arr2[$k]);
-
- if ($d) {
- $diff[$k] = $d;
+class ArrayHelper
+{
+ public static function array_diff_key_recursive(array $arr1, array $arr2)
+ {
+ $diff = array_diff_key($arr1, $arr2);
+ $intersect = array_intersect_key($arr1, $arr2);
+
+ foreach ($intersect as $k => $v) {
+ if (is_array($arr1[$k]) && is_array($arr2[$k])) {
+ $d = array_diff_key_recursive($arr1[$k], $arr2[$k]);
+
+ if ($d) {
+ $diff[$k] = $d;
+ }
}
}
+
+ return $diff;
}
-
- return $diff;
}
-
-?>
\ No newline at end of file
diff --git a/src/helper/IdpHelper.php b/src/helper/IdpHelper.php
new file mode 100644
index 0000000..e238a4b
--- /dev/null
+++ b/src/helper/IdpHelper.php
@@ -0,0 +1,36 @@
+xpath('//ns0:EntityDescriptor/@entityID')[0];
+ $metadata['idp_sso'] = $xml->xpath('//ns0:SingleSignOnService/@Location')[0];
+ $metadata['idp_slo'] = $xml->xpath('//ns0:SingleLogoutService/@Location')[0];
+ $metadata['idp_cert'] = $xml->xpath('//ns1:X509Certificate')[0];
+
+ file_put_contents("../config/idp/" . $idpName, print_r($metadata, true));
+
+ return $metadata;
+ }
+}
\ No newline at end of file
diff --git a/src/saml_strategy/PhpSamlOneLogin.php b/src/saml_strategy/PhpSamlOneLogin.php
index 229c67a..9de9f66 100644
--- a/src/saml_strategy/PhpSamlOneLogin.php
+++ b/src/saml_strategy/PhpSamlOneLogin.php
@@ -1,36 +1,45 @@
init($settings);
+ if (filter_var($idpUrl, FILTER_VALIDATE_URL)) {
+ throw new Exception("The provided idp URL is not a valid URL", 1);
+ }
+ $this->init($idpUrl, $settings);
print_r($this->settings);
}
- private function init($settings)
+ private function init($idpUrl, $settings)
{
- require_once(__DIR__ . '/../config/OneloginSamlConfig.php');
+ $settingsHelper = new OneloginSamlConfig();
+ $defaultSettings = $settingsHelper->getSettings();
if (!is_null($settings)) {
- $diff = array_diff_key_recursive($settings, $defaultSettings);
+ $diff = ArrayHelper::array_diff_key_recursive($settings, $defaultSettings);
if (!empty($diff)) {
- $message = "The following keys are invalid for settings array: ";
- array_walk_recursive($diff, function($v, $k) {
+ $message = "The following keys are invalid for the provided settings array: ";
+ array_walk_recursive($diff, function ($v, $k) {
$message .= $k . ", ";
});
throw new Exception($message, 1);
}
}
$this->settings = is_null($settings) ? $defaultSettings : array_merge_recursive($defaultSettings, $settings);
-
+ $metadata = IdpHelper::getMetadata($idpUrl);
+
+
$auth = new OneLogin_Saml2_Auth($this->settings);
}
@@ -45,15 +54,15 @@ public function login()
if (isset($_SESSION['AuthNRequestID'])) {
$requestID = $_SESSION['AuthNRequestID'];
}
-
+
$auth->processResponse($requestID);
unset($_SESSION['AuthNRequestID']);
-
+
$errors = $auth->getErrors();
if (!empty($errors)) {
return $errors;
}
-
+
if (!$auth->isAuthenticated()) {
return false;
}
@@ -71,7 +80,7 @@ public function login()
}
public function logout()
- {
+ {
if (!$auth->isAuthenticated()) {
return false;
}
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 'Name | Values | ';
- foreach ($attributes as $attributeName => $attributeValues) {
- echo '' . htmlentities($attributeName) . ' | ';
- foreach ($attributeValues as $attributeValue) {
- echo '- ' . htmlentities($attributeValue) . '
';
- }
- echo ' |
';
- }
- 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
index 4b1d796..963f930 100644
--- a/www/index.php
+++ b/www/index.php
@@ -3,121 +3,9 @@
/**
* SAML Handler
*/
-
session_start();
require_once("../vendor/autoload.php");
+require_once("../src/saml_strategy/PhpSamlOneLogin.php");
-use OneLogin\Saml2\Auth;
-use OneLogin\Saml2\Utils;
-
-require_once 'settings.php';
-
-$auth = new Auth($settingsInfo);
-
-if (isset($_GET['sso'])) {
- $auth->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 'Name | Values | ';
- foreach ($attributes as $attributeName => $attributeValues) {
- echo '' . htmlentities($attributeName) . ' | ';
- foreach ($attributeValues as $attributeValue) {
- echo '- ' . htmlentities($attributeValue) . '
';
- }
- echo ' |
';
- }
- 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
';
-}
+$onelogin = new PhpSamlOneLogin;
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 'Name | Values | ';
- foreach ($attributes as $attributeName => $attributeValues) {
- echo '' . htmlentities($attributeName) . ' | ';
- foreach ($attributeValues as $attributeValue) {
- echo '- ' . htmlentities($attributeValue) . '
';
- }
- echo ' |
';
- }
- 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 'Name | Values | ';
- foreach ($attributes as $attributeName => $attributeValues) {
- echo '' . htmlentities($attributeName) . ' | ';
- foreach ($attributeValues as $attributeValue) {
- echo '- ' . htmlentities($attributeValue) . '
';
- }
- echo ' |
';
- }
- 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/www3/index.php b/www3/index.php
deleted file mode 100644
index 963f930..0000000
--- a/www3/index.php
+++ /dev/null
@@ -1,11 +0,0 @@
-
Date: Fri, 20 Jul 2018 17:48:35 +0200
Subject: [PATCH 07/69] added automatic idp metadata configuration
---
src/config/OneloginSamlConfig.php | 40 +++++++++++++++++---------
src/saml_strategy/PhpSamlInterface.php | 1 +
src/saml_strategy/PhpSamlOneLogin.php | 15 +++++++---
3 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/src/config/OneloginSamlConfig.php b/src/config/OneloginSamlConfig.php
index 1f76a2a..971119a 100644
--- a/src/config/OneloginSamlConfig.php
+++ b/src/config/OneloginSamlConfig.php
@@ -2,23 +2,23 @@
class OneloginSamlConfig
{
- // Default values
- var $spBaseUrl = '';
- var $idpEntityId = '';
- var $spAcsUrl = null;
- var $spSloUrl = null;
- var $idpSSO = null;
- var $idpSLO = null;
- var $spKeyFile = 'sp.key';
- var $spCrtFile = 'sp.crt';
- var $idpCertFile = '';
+ // Default values SP
+ private $spBaseUrl = null;
+ private $spKeyFile = 'sp.key';
+ private $spCrtFile = 'sp.crt';
+ private $spAcsUrl = null;
+ private $spSloUrl = null;
+ // Default values IDP
+ private $idpEntityId = null;
+ private $idpSSO = null;
+ private $idpSLO = null;
+ private $idpCertFile = null;
function __construct()
{
+ // Default values
$this->spAcsUrl = $this->spBaseUrl . '/index.php?acs';
$this->spSloUrl = $this->spBaseUrl . '/index.php?sls';
- $this->idpSSO = $this->idpEntityId . '/sso';
- $this->idpSLO = $this->idpEntityId . '/slo';
}
public function getSettings()
@@ -67,6 +67,20 @@ public function getSettings()
}
public function updateSettings($settings) {
-
+ foreach ($settings as $key => $value) {
+ if (property_exists($key) && strpos("idp", $key) === false) {
+ $this->{$key} = $value;
+ }
+ }
+ return $this->getSettings();
+ }
+
+ public function updateIdpMetadata($metadata) {
+ foreach ($metadata as $key => $value) {
+ if (property_exists($key) && strpos("idp", $key) !== false) {
+ $this->{$key} = $value;
+ }
+ }
+ return $this->getSettings();
}
}
\ No newline at end of file
diff --git a/src/saml_strategy/PhpSamlInterface.php b/src/saml_strategy/PhpSamlInterface.php
index 9454590..cdf38b0 100644
--- a/src/saml_strategy/PhpSamlInterface.php
+++ b/src/saml_strategy/PhpSamlInterface.php
@@ -2,6 +2,7 @@
interface PhpSamlInterface {
public function init($settings);
+ public function isAuthenticated();
public function login();
public function logout();
}
\ No newline at end of file
diff --git a/src/saml_strategy/PhpSamlOneLogin.php b/src/saml_strategy/PhpSamlOneLogin.php
index 9de9f66..afa9f86 100644
--- a/src/saml_strategy/PhpSamlOneLogin.php
+++ b/src/saml_strategy/PhpSamlOneLogin.php
@@ -25,9 +25,8 @@ function __construct($idpUrl, $settings = null)
private function init($idpUrl, $settings)
{
$settingsHelper = new OneloginSamlConfig();
- $defaultSettings = $settingsHelper->getSettings();
if (!is_null($settings)) {
- $diff = ArrayHelper::array_diff_key_recursive($settings, $defaultSettings);
+ $diff = ArrayHelper::array_diff_key_recursive($settings, get_object_vars($settingsHelper));
if (!empty($diff)) {
$message = "The following keys are invalid for the provided settings array: ";
array_walk_recursive($diff, function ($v, $k) {
@@ -35,12 +34,20 @@ private function init($idpUrl, $settings)
});
throw new Exception($message, 1);
}
+ $settingsHelper->updateSpSettings($settings);
}
- $this->settings = is_null($settings) ? $defaultSettings : array_merge_recursive($defaultSettings, $settings);
$metadata = IdpHelper::getMetadata($idpUrl);
+ $settingsHelper->updateIdpMetadata($metadata);
+ $auth = new OneLogin_Saml2_Auth($settingsHelper->getSettings());
+ }
- $auth = new OneLogin_Saml2_Auth($this->settings);
+ public function isAuthenticated()
+ {
+ if ($auth->isAuthenticated) {
+ return false;
+ }
+ return true;
}
public function login()
From 7a20325c773ab4d56b3059f2004fa164dc7ada4d Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 20 Jul 2018 18:04:57 +0200
Subject: [PATCH 08/69] changed idp metadata storage to xml
---
src/helper/IdpHelper.php | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/helper/IdpHelper.php b/src/helper/IdpHelper.php
index e238a4b..c2bdb3b 100644
--- a/src/helper/IdpHelper.php
+++ b/src/helper/IdpHelper.php
@@ -7,7 +7,7 @@ public static function getMetadata($idpUrl)
// Check if a file containing this idp metadata already exists
$idpName = str_replace(".", "_", parse_url($idpUrl, PHP_URL_HOST));
if (file_exists("../config/idp/" . $idpName)) {
- $metadata = file_get_contents("../config/idp/" . $idpName);
+ $metadata = simplexml_load_file("../config/idp/" . $idpName . '.xml');
return $metadata;
}
@@ -22,15 +22,18 @@ public static function getMetadata($idpUrl)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$data = curl_exec($ch);
curl_close($ch);
+
+ $dom = new DOMDocument();
+ $dom->loadXML($data);
+ $dom->save("../config/idp/" . $idpName . ".xml");
+
$xml = new SimpleXMLElement($data);
$metadata = array();
$metadata['idp_entityid'] = $xml->xpath('//ns0:EntityDescriptor/@entityID')[0];
$metadata['idp_sso'] = $xml->xpath('//ns0:SingleSignOnService/@Location')[0];
$metadata['idp_slo'] = $xml->xpath('//ns0:SingleLogoutService/@Location')[0];
$metadata['idp_cert'] = $xml->xpath('//ns1:X509Certificate')[0];
-
- file_put_contents("../config/idp/" . $idpName, print_r($metadata, true));
-
+
return $metadata;
}
}
\ No newline at end of file
From 439104ffb437f7c2fc77fdef150d66f706dd5421 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 20 Jul 2018 18:10:50 +0200
Subject: [PATCH 09/69] added interface methods to generic PhpSaml class
---
src/PhpSaml.php | 23 +++++++++++++++++++----
src/saml_strategy/PhpSamlInterface.php | 1 -
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/src/PhpSaml.php b/src/PhpSaml.php
index accfdb5..fee9de1 100644
--- a/src/PhpSaml.php
+++ b/src/PhpSaml.php
@@ -1,9 +1,9 @@
php_saml = new PhpSamlOneLogin($idpUrl, $settings);
+ $this->phpSaml = new PhpSamlOneLogin($idpUrl, $settings);
break;
default:
- $this->php_saml = new PhpSamlOneLogin($idpUrl, $settings);
+ $this->phpSaml = new PhpSamlOneLogin($idpUrl, $settings);
break;
}
}
+ public function isAuthenticated()
+ {
+ $this->phpSaml->isAuthenticated();
+ }
+
+ public function login()
+ {
+ $this->phpSaml->login();
+ }
+
+ public function logout()
+ {
+ $this->phpSaml->logout();
+ }
+
}
\ No newline at end of file
diff --git a/src/saml_strategy/PhpSamlInterface.php b/src/saml_strategy/PhpSamlInterface.php
index cdf38b0..bdee638 100644
--- a/src/saml_strategy/PhpSamlInterface.php
+++ b/src/saml_strategy/PhpSamlInterface.php
@@ -1,7 +1,6 @@
Date: Sat, 21 Jul 2018 00:41:55 +0200
Subject: [PATCH 10/69] WIP readme
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index 1296dc5..17895df 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
# spid-php2
+Work in progress. Do not merge this branch.
+
Software Development Kit (SDK) for easy SPID SSO integration based on [php-saml](https://github.com/onelogin/php-saml).
This component acts as a SPID SP (Service Provider) and logs you in via an external IDP (IDentity Provider).
From 5362c0e86572ce459eaaa263d3aa8d256d6a0418 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 26 Jul 2018 08:34:58 +0200
Subject: [PATCH 11/69] modifica getmetadata idp
---
.DS_Store | Bin 0 -> 8196 bytes
{www => example}/index.php | 0
src/PhpSaml.php | 8 +++---
src/helper/IdpHelper.php | 37 ++++++--------------------
src/saml_strategy/PhpSamlOneLogin.php | 10 +++----
5 files changed, 17 insertions(+), 38 deletions(-)
create mode 100644 .DS_Store
rename {www => example}/index.php (100%)
diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..f82ed19c8c40230dfce7d7f02e7b2ba3225d6d8d
GIT binary patch
literal 8196
zcmeHM&2G~`5S~p+>l9Tje`+sCz94aEP}5RzK$Sw894Y~-2!aEk)_-kH9Xr@g(-MMm
z;T?cC;88enY@pmI5P8O@l&
z=XpI*N^0Z=B!fOtNKeS4H`GI`i)KJGpc&8%Xa+O`|04re$B&B$Cpb;qm;%=J1+Sv#q
z#||PJXxw1z2juOaq6m{^vVjZpD7s%j&5%P8b*PIr!54xU_FtnH6*WuN88idvIkcbm
zS^8Gcye52x*n>~I@OMNORuG`)(V^&fapmQ$l-CMYrsyGU&^oo~F}10cM~i)a%&>74
z=m_2-!RntcB7b3&zQAMFhCz?8x_zvYul&Rc*?a+C!Izg7;@E^<3%l!(n_ngSP|&yu
z<|P+Z^c+OrgO){A)C4~spA^0k9gHo*<`U{5W{Q^iX~?eK1ZKSD4y>k_b5Xghg3V1Z
z+f===_Qh$)+Mk5|F4p4k73Oy-;y(_{nLNs4MU=DHGVI3WMB?%AsUG>U@bzGXl2z5dqR
z_4O!BEkE>Pq3pXJATOW$p&RuZQ7?28VW%x845MOHw&oTFgOz)W=H1%LaM2vpYAef&
z=IUx~III}+w`yw}+nuAggLlLCpAaY%rrx16E3c2+&*&)<4%%@TMBy%nqfXKR2n-Rp
zh~hj!;wa_`>Jxqi6hD4h)GUq?x9A}B+2c3%2=H5s8JSyb3fl5E9&;dh$a3g;g?8bI
zKL)Dep%BCW8GQ5o<*Z>Nx@ZQ@KLcgCg$17fw@&~5fBrYBcc2;244ldUn`pM14NU+3
zyP$~VxweVAjmithjieMRXhb>=DbjJs<9`^UZvx77>Pn8J#0bj2{}7phpSaml = new PhpSamlOneLogin($idpUrl, $settings);
+ $this->phpSaml = new PhpSamlOneLogin($idpName, $settings);
break;
default:
- $this->phpSaml = new PhpSamlOneLogin($idpUrl, $settings);
+ $this->phpSaml = new PhpSamlOneLogin($idpName, $settings);
break;
}
}
diff --git a/src/helper/IdpHelper.php b/src/helper/IdpHelper.php
index c2bdb3b..236632f 100644
--- a/src/helper/IdpHelper.php
+++ b/src/helper/IdpHelper.php
@@ -2,38 +2,17 @@
class IdpHelper
{
- public static function getMetadata($idpUrl)
+ public static function getMetadata($idpName)
{
- // Check if a file containing this idp metadata already exists
- $idpName = str_replace(".", "_", parse_url($idpUrl, PHP_URL_HOST));
if (file_exists("../config/idp/" . $idpName)) {
- $metadata = simplexml_load_file("../config/idp/" . $idpName . '.xml');
+ $xml = simplexml_load_file("../config/idp/" . $idpName . '.xml');
+ $metadata = array();
+ $metadata['idp_entityid'] = $xml->xpath('//ns0:EntityDescriptor/@entityID')[0];
+ $metadata['idp_sso'] = $xml->xpath('//ns0:SingleSignOnService/@Location')[0];
+ $metadata['idp_slo'] = $xml->xpath('//ns0:SingleLogoutService/@Location')[0];
+ $metadata['idp_cert'] = $xml->xpath('//ns1:X509Certificate')[0];
+
return $metadata;
}
-
- // File doesn't exist yet, get metadata from idp url and save it to file
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $idpUrl);
- 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);
-
- $dom = new DOMDocument();
- $dom->loadXML($data);
- $dom->save("../config/idp/" . $idpName . ".xml");
-
- $xml = new SimpleXMLElement($data);
- $metadata = array();
- $metadata['idp_entityid'] = $xml->xpath('//ns0:EntityDescriptor/@entityID')[0];
- $metadata['idp_sso'] = $xml->xpath('//ns0:SingleSignOnService/@Location')[0];
- $metadata['idp_slo'] = $xml->xpath('//ns0:SingleLogoutService/@Location')[0];
- $metadata['idp_cert'] = $xml->xpath('//ns1:X509Certificate')[0];
-
- return $metadata;
}
}
\ No newline at end of file
diff --git a/src/saml_strategy/PhpSamlOneLogin.php b/src/saml_strategy/PhpSamlOneLogin.php
index afa9f86..a2d34c8 100644
--- a/src/saml_strategy/PhpSamlOneLogin.php
+++ b/src/saml_strategy/PhpSamlOneLogin.php
@@ -13,16 +13,16 @@ class PhpSamlOneLogin implements PhpSamlInterface
var $settings;
var $auth;
- function __construct($idpUrl, $settings = null)
+ function __construct($idpName, $settings = null)
{
- if (filter_var($idpUrl, FILTER_VALIDATE_URL)) {
+ if (filter_var($idpName, FILTER_VALIDATE_URL)) {
throw new Exception("The provided idp URL is not a valid URL", 1);
}
- $this->init($idpUrl, $settings);
+ $this->init($idpName, $settings);
print_r($this->settings);
}
- private function init($idpUrl, $settings)
+ private function init($idpName, $settings)
{
$settingsHelper = new OneloginSamlConfig();
if (!is_null($settings)) {
@@ -36,7 +36,7 @@ private function init($idpUrl, $settings)
}
$settingsHelper->updateSpSettings($settings);
}
- $metadata = IdpHelper::getMetadata($idpUrl);
+ $metadata = IdpHelper::getMetadata($idpName);
$settingsHelper->updateIdpMetadata($metadata);
$auth = new OneLogin_Saml2_Auth($settingsHelper->getSettings());
From 30262b844545177de620074d90432956cc42149e Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 26 Jul 2018 09:02:15 +0200
Subject: [PATCH 12/69] added sp cert settings
---
src/config/OneloginSamlConfig.php | 32 ++++++++++++++++++---------
src/helper/SpHelper.php | 27 ++++++++++++++++++++++
src/saml_strategy/PhpSamlOneLogin.php | 13 ++++++-----
3 files changed, 57 insertions(+), 15 deletions(-)
create mode 100644 src/helper/SpHelper.php
diff --git a/src/config/OneloginSamlConfig.php b/src/config/OneloginSamlConfig.php
index 971119a..d35c5da 100644
--- a/src/config/OneloginSamlConfig.php
+++ b/src/config/OneloginSamlConfig.php
@@ -3,7 +3,8 @@
class OneloginSamlConfig
{
// Default values SP
- private $spBaseUrl = null;
+ private $spBaseUrl = '';
+ private $spEntityId = null;
private $spKeyFile = 'sp.key';
private $spCrtFile = 'sp.crt';
private $spAcsUrl = null;
@@ -19,6 +20,7 @@ function __construct()
// Default values
$this->spAcsUrl = $this->spBaseUrl . '/index.php?acs';
$this->spSloUrl = $this->spBaseUrl . '/index.php?sls';
+ $this->spEntityId = $this->spBaseUrl . '/metadata.php';
}
public function getSettings()
@@ -34,26 +36,26 @@ public function getSettings()
'debug' => true,
'sp' => array(
- 'entityId' => $spBaseUrl . '/metadata.php',
+ 'entityId' => $this->spEntityId,
'assertionConsumerService' => array(
- 'url' => $spAcsUrl,
+ 'url' => $this->spAcsUrl,
),
'singleLogoutService' => array(
- 'url' => $spSloUrl,
+ 'url' => $this->spSloUrl,
),
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
- 'x509cert' => $spCrtFile,
- 'privateKey' => $spKeyFile,
+ 'x509cert' => $this->spCrtFile,
+ 'privateKey' => $this->spKeyFile,
),
'idp' => array(
- 'entityId' => $idpEntityId,
+ 'entityId' => $this->idpEntityId,
'singleSignOnService' => array(
- 'url' => $idpSSO,
+ 'url' => $this->idpSSO,
),
'singleLogoutService' => array(
- 'url' => $idpSLO,
+ 'url' => $this->idpSLO,
),
- 'x509cert' => $idpCertFile,
+ 'x509cert' => $this->idpCertFile,
),
'security' => array(
'authnRequestsSigned' => true,
@@ -83,4 +85,14 @@ public function updateIdpMetadata($metadata) {
}
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();
+ }
}
\ No newline at end of file
diff --git a/src/helper/SpHelper.php b/src/helper/SpHelper.php
new file mode 100644
index 0000000..1476e9c
--- /dev/null
+++ b/src/helper/SpHelper.php
@@ -0,0 +1,27 @@
+init($idpName, $settings);
+ $this->init($idpMetadataFile, $spCertFile, $spKeyFile, $settings);
print_r($this->settings);
}
- private function init($idpName, $settings)
+ private function init($idpMetadataFile, $spCertFile, $spKeyFile, $settings)
{
$settingsHelper = new OneloginSamlConfig();
if (!is_null($settings)) {
@@ -36,9 +36,12 @@ private function init($idpName, $settings)
}
$settingsHelper->updateSpSettings($settings);
}
- $metadata = IdpHelper::getMetadata($idpName);
+ $metadata = IdpHelper::getMetadata($idpMetadataFile);
$settingsHelper->updateIdpMetadata($metadata);
+ $sp = SpHelper::getSpCert($spCertFile, $spKeyFile);
+ $settingsHelper->updateSpData($sp);
+
$auth = new OneLogin_Saml2_Auth($settingsHelper->getSettings());
}
From d00cbc54d651416a885d5287a6b01021ee5fbf61 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 26 Jul 2018 09:46:08 +0200
Subject: [PATCH 13/69] added namespaces
---
.DS_Store | Bin 8196 -> 8196 bytes
bin/Configuration.php | 8 ----
bin/configure.php | 63 -------------------------
composer.json | 8 ++--
src/PhpSaml.php | 5 ++
src/config/OneloginSamlConfig.php | 7 ++-
src/helper/ArrayHelper.php | 2 +
src/helper/IdpHelper.php | 2 +
src/helper/SpHelper.php | 2 +
src/saml_strategy/PhpSamlInterface.php | 2 +
src/saml_strategy/PhpSamlOneLogin.php | 12 +++--
11 files changed, 31 insertions(+), 80 deletions(-)
delete mode 100644 bin/Configuration.php
delete mode 100755 bin/configure.php
diff --git a/.DS_Store b/.DS_Store
index f82ed19c8c40230dfce7d7f02e7b2ba3225d6d8d..2137870ec5135ccb2df51ce4b88d941bb650d631 100644
GIT binary patch
delta 131
zcmZp1XmOa}&nUhzU^hRb_+}mfbw=J)h6;v6hFpdMh8%{}$*Cgpn+*kZnR(e5${11^
y@)%MW@)?RIy9nQqL=h './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/composer.json b/composer.json
index b4cc511..4274d76 100644
--- a/composer.json
+++ b/composer.json
@@ -12,9 +12,11 @@
],
"post-update-cmd": [
"setup\\Configuration::setup"
- ],
+ ],
"autoload": {
- "classmap": ["bin/"]
- }
+ "psr-4": {
+ "SpidPHP\\": "src/"
+ }
+ }
}
}
diff --git a/src/PhpSaml.php b/src/PhpSaml.php
index 8b336f7..0a8cbb7 100644
--- a/src/PhpSaml.php
+++ b/src/PhpSaml.php
@@ -1,5 +1,10 @@
false,
+ 'strict' => true,
// Enable debug mode (to print errors).
'debug' => true,
@@ -70,7 +72,8 @@ public function getSettings()
public function updateSettings($settings) {
foreach ($settings as $key => $value) {
- if (property_exists($key) && strpos("idp", $key) === false) {
+ // do not update idp os sp cert file values, they are updated in their own method
+ if (property_exists($key) && strpos("idp", $key) === false && strpos("file", $key) === false) {
$this->{$key} = $value;
}
}
diff --git a/src/helper/ArrayHelper.php b/src/helper/ArrayHelper.php
index 7737567..29154a0 100644
--- a/src/helper/ArrayHelper.php
+++ b/src/helper/ArrayHelper.php
@@ -1,5 +1,7 @@
Date: Thu, 26 Jul 2018 10:01:35 +0200
Subject: [PATCH 14/69] WIP: basic example
---
example/index.php | 22 ++++++++++++++++++++--
src/PhpSaml.php | 6 +++---
2 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/example/index.php b/example/index.php
index 963f930..825f182 100644
--- a/example/index.php
+++ b/example/index.php
@@ -6,6 +6,24 @@
session_start();
require_once("../vendor/autoload.php");
-require_once("../src/saml_strategy/PhpSamlOneLogin.php");
-$onelogin = new PhpSamlOneLogin;
+use SpidPHP\PhpSaml;
+
+$settings = [
+ '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',
+ ),
+ ];
+
+$onelogin = new PhpSaml("http://idp.simevo.com", $settings);
+
+if (!$onelogin->isAuthenticated()) $onelogin->login();
+
+if ($onelogin->login()) $onelogin->logout();
diff --git a/src/PhpSaml.php b/src/PhpSaml.php
index 0a8cbb7..9b14ac3 100644
--- a/src/PhpSaml.php
+++ b/src/PhpSaml.php
@@ -10,7 +10,7 @@ class PhpSaml implements PhpSamlInterface
private $phpSaml = null;
- public function __construct($idpName, $settings = null, $mode = 'onelogin')
+ public function __construct($idpMetadataFile, $spCertFile, $spKeyFile, $settings = null, $mode = 'onelogin')
{
if (session_status() == PHP_SESSION_NONE) {
@@ -19,10 +19,10 @@ public function __construct($idpName, $settings = null, $mode = 'onelogin')
switch ($mode) {
case 'onelogin':
- $this->phpSaml = new PhpSamlOneLogin($idpName, $settings);
+ $this->phpSaml = new PhpSamlOneLogin($idpMetadataFile, $spCertFile, $spKeyFile, $settings);
break;
default:
- $this->phpSaml = new PhpSamlOneLogin($idpName, $settings);
+ $this->phpSaml = new PhpSamlOneLogin($idpMetadataFile, $spCertFile, $spKeyFile, $settings);
break;
}
}
From bec70c06bc464d140ea526d366f5b14ab09dab75 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 26 Jul 2018 12:51:37 +0200
Subject: [PATCH 15/69] moving all settings to array format
---
example/index.php | 2 +-
src/PhpSaml.php | 28 +++++++++++++++------
src/config/OneloginSamlConfig.php | 28 ++++++++++++++++++---
src/helper/IdpHelper.php | 19 +++++++-------
src/saml_strategy/PhpSamlInterface.php | 3 ++-
src/saml_strategy/PhpSamlOneLogin.php | 34 ++++++++++++--------------
6 files changed, 73 insertions(+), 41 deletions(-)
diff --git a/example/index.php b/example/index.php
index 825f182..48604af 100644
--- a/example/index.php
+++ b/example/index.php
@@ -22,7 +22,7 @@
),
];
-$onelogin = new PhpSaml("http://idp.simevo.com", $settings);
+$onelogin = new PhpSaml("http://idp.simevo.com", "/sp.key", "/sp.crt", $settings);
if (!$onelogin->isAuthenticated()) $onelogin->login();
diff --git a/src/PhpSaml.php b/src/PhpSaml.php
index 9b14ac3..693cc8b 100644
--- a/src/PhpSaml.php
+++ b/src/PhpSaml.php
@@ -9,31 +9,45 @@ class PhpSaml implements PhpSamlInterface
{
private $phpSaml = null;
+ private $mode = null;
+ private $settings = null;
- public function __construct($idpMetadataFile, $spCertFile, $spKeyFile, $settings = null, $mode = 'onelogin')
+ public function __construct($settings = null, $mode = 'onelogin')
{
-
+ /*
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
+ */
+
+ $this->mode = $mode;
+ $this->settings = $settings;
+ }
- switch ($mode) {
+ private function initStrategy()
+ {
+ switch ($this->mode) {
case 'onelogin':
- $this->phpSaml = new PhpSamlOneLogin($idpMetadataFile, $spCertFile, $spKeyFile, $settings);
+ $this->phpSaml = new PhpSamlOneLogin($this->settings);
break;
default:
- $this->phpSaml = new PhpSamlOneLogin($idpMetadataFile, $spCertFile, $spKeyFile, $settings);
+ $this->phpSaml = new PhpSamlOneLogin($this->settings);
break;
}
}
+ public function getSupportedIdps()
+ {
+ return array();
+ }
+
public function isAuthenticated()
{
$this->phpSaml->isAuthenticated();
}
- public function login()
- {
+ public function login( $idpName, $redirectTo = null, $level = 1 )
+ {
$this->phpSaml->login();
}
diff --git a/src/config/OneloginSamlConfig.php b/src/config/OneloginSamlConfig.php
index 4a87ab7..22137dc 100644
--- a/src/config/OneloginSamlConfig.php
+++ b/src/config/OneloginSamlConfig.php
@@ -2,6 +2,10 @@
namespace SpidPHP\Config;
+use SpidPHP\Helpers\SpHelper;
+use SpidPHP\Helpers\IdpHelper;
+
+
class OneloginSamlConfig
{
// Default values SP
@@ -9,6 +13,8 @@ class OneloginSamlConfig
private $spEntityId = null;
private $spKeyFile = 'sp.key';
private $spCrtFile = 'sp.crt';
+ private $spKeyFileValue = null;
+ private $spCrtFileValue = null;
private $spAcsUrl = null;
private $spSloUrl = null;
// Default values IDP
@@ -17,6 +23,8 @@ class OneloginSamlConfig
private $idpSLO = null;
private $idpCertFile = null;
+ private $is_not_updatable = ['spKeyFileValue', 'spCrtFileValue', 'idpEntityId', 'idpSSO', 'idpSLO', 'idpCertFile'];
+
function __construct()
{
// Default values
@@ -27,7 +35,7 @@ function __construct()
public function getSettings()
{
- return $defaultSettings = array(
+ 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
@@ -73,14 +81,26 @@ public function getSettings()
public function updateSettings($settings) {
foreach ($settings as $key => $value) {
// do not update idp os sp cert file values, they are updated in their own method
- if (property_exists($key) && strpos("idp", $key) === false && strpos("file", $key) === false) {
- $this->{$key} = $value;
+ if (!property_exists($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 and .cert files is invalid", 1);
}
+ $sp = SpHelper::getSpCert($this->spKeyFile, $this->spCrtFile);
+ $this->updateSpData($sp);
return $this->getSettings();
}
- public function updateIdpMetadata($metadata) {
+ public function updateIdpMetadata($idpName) {
+ $metadata = IdpHelper::getMetadata($idpName);
foreach ($metadata as $key => $value) {
if (property_exists($key) && strpos("idp", $key) !== false) {
$this->{$key} = $value;
diff --git a/src/helper/IdpHelper.php b/src/helper/IdpHelper.php
index c4c6b3e..272b606 100644
--- a/src/helper/IdpHelper.php
+++ b/src/helper/IdpHelper.php
@@ -6,15 +6,16 @@ class IdpHelper
{
public static function getMetadata($idpName)
{
- if (file_exists("../config/idp/" . $idpName)) {
- $xml = simplexml_load_file("../config/idp/" . $idpName . '.xml');
- $metadata = array();
- $metadata['idp_entityid'] = $xml->xpath('//ns0:EntityDescriptor/@entityID')[0];
- $metadata['idp_sso'] = $xml->xpath('//ns0:SingleSignOnService/@Location')[0];
- $metadata['idp_slo'] = $xml->xpath('//ns0:SingleLogoutService/@Location')[0];
- $metadata['idp_cert'] = $xml->xpath('//ns1:X509Certificate')[0];
-
- return $metadata;
+ if (!file_exists("../config/idp/" . $idpName)) {
+ throw new Exception("Invalid IDP Requested", 1);
}
+ $xml = simplexml_load_file("../config/idp/" . $idpName . '.xml');
+ $metadata = array();
+ $metadata['idp_entityid'] = $xml->xpath('//ns0:EntityDescriptor/@entityID')[0];
+ $metadata['idp_sso'] = $xml->xpath('//ns0:SingleSignOnService/@Location')[0];
+ $metadata['idp_slo'] = $xml->xpath('//ns0:SingleLogoutService/@Location')[0];
+ $metadata['idp_cert'] = $xml->xpath('//ns1:X509Certificate')[0];
+
+ return $metadata;
}
}
\ No newline at end of file
diff --git a/src/saml_strategy/PhpSamlInterface.php b/src/saml_strategy/PhpSamlInterface.php
index 31b8488..e12b173 100644
--- a/src/saml_strategy/PhpSamlInterface.php
+++ b/src/saml_strategy/PhpSamlInterface.php
@@ -3,7 +3,8 @@
namespace SpidPHP\Strategy\Interfaces;
interface PhpSamlInterface {
+ public function getSupportedIdps();
public function isAuthenticated();
- public function login();
+ public function login( $idpName, $redirectTo = null, $level = 1 );
public function logout();
}
\ No newline at end of file
diff --git a/src/saml_strategy/PhpSamlOneLogin.php b/src/saml_strategy/PhpSamlOneLogin.php
index 8b989f2..60993cf 100644
--- a/src/saml_strategy/PhpSamlOneLogin.php
+++ b/src/saml_strategy/PhpSamlOneLogin.php
@@ -14,23 +14,21 @@
class PhpSamlOneLogin implements PhpSamlInterface
{
- var $settings;
- var $auth;
+ private $settings;
+ private $auth;
- function __construct($idpMetadataFile, $spCertFile, $spKeyFile, $settings = null)
+ function __construct($settings)
{
- if (filter_var($idpMetadataFile, FILTER_VALIDATE_URL)) {
- throw new Exception("The provided idp URL is not a valid URL", 1);
- }
- $this->init($idpMetadataFile, $spCertFile, $spKeyFile, $settings);
+ $this->settings = $settings;
+ $this->init($settings);
print_r($this->settings);
}
- private function init($idpMetadataFile, $spCertFile, $spKeyFile, $settings)
+ private function init($idpName)
{
$settingsHelper = new OneloginSamlConfig();
- if (!is_null($settings)) {
- $diff = ArrayHelper::array_diff_key_recursive($settings, get_object_vars($settingsHelper));
+ if (!is_null($this->settings)) {
+ $diff = ArrayHelper::array_diff_key_recursive($this->settings, get_object_vars($settingsHelper));
if (!empty($diff)) {
$message = "The following keys are invalid for the provided settings array: ";
array_walk_recursive($diff, function ($v, $k) {
@@ -38,27 +36,24 @@ private function init($idpMetadataFile, $spCertFile, $spKeyFile, $settings)
});
throw new Exception($message, 1);
}
- $settingsHelper->updateSpSettings($settings);
+ $settingsHelper->updateSettings($this->settings);
}
- $metadata = IdpHelper::getMetadata($idpMetadataFile);
- $settingsHelper->updateIdpMetadata($metadata);
-
- $sp = SpHelper::getSpCert($spCertFile, $spKeyFile);
- $settingsHelper->updateSpData($sp);
-
- $auth = new OneLogin_Saml2_Auth($settingsHelper->getSettings());
+ $settingsHelper->updateIdpMetadata($idpName);
+ $this->auth = new OneLogin_Saml2_Auth($settingsHelper->getSettings());
}
public function isAuthenticated()
{
+ if (is_null($this->auth)) return false;
if ($auth->isAuthenticated) {
return false;
}
return true;
}
- public function login()
+ public function login( $idpName, $redirectTo = null, $level = 1 )
{
+ if (is_null($this->auth)) $this->init($idpName);
if ($auth->isAuthenticated) {
return false;
}
@@ -95,6 +90,7 @@ public function login()
public function logout()
{
+ if (is_null($this->auth)) return false;
if (!$auth->isAuthenticated()) {
return false;
}
From 88c69c1ba592a543c3c52a9204ef1f482f939ed6 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 26 Jul 2018 14:52:58 +0200
Subject: [PATCH 16/69] Fix namespace and test settings generation
---
.vscode/launch.json | 22 ++++++++++++
composer.json | 10 +++---
composer.lock | 29 ++++++++--------
example/index.php | 25 ++++++--------
src/{helper => Helpers}/ArrayHelper.php | 0
src/{helper => Helpers}/IdpHelper.php | 2 +-
src/{helper => Helpers}/SpHelper.php | 0
src/PhpSaml.php | 21 +++++-------
.../Interfaces}/PhpSamlInterface.php | 0
.../PhpSamlOneLogin.php | 34 ++++++++++---------
src/config/OneloginSamlConfig.php | 28 +++++++--------
11 files changed, 94 insertions(+), 77 deletions(-)
create mode 100644 .vscode/launch.json
rename src/{helper => Helpers}/ArrayHelper.php (100%)
rename src/{helper => Helpers}/IdpHelper.php (91%)
rename src/{helper => Helpers}/SpHelper.php (100%)
rename src/{saml_strategy => Strategy/Interfaces}/PhpSamlInterface.php (100%)
rename src/{saml_strategy => Strategy}/PhpSamlOneLogin.php (75%)
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..9d9ed65
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,22 @@
+{
+ // Usare IntelliSense per informazioni sui possibili attributi.
+ // Al passaggio del mouse vengono visualizzate le descrizioni degli attributi esistenti.
+ // Per ulteriori informazioni, visitare: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Listen for XDebug",
+ "type": "php",
+ "request": "launch",
+ "port": 9000
+ },
+ {
+ "name": "Launch currently open script",
+ "type": "php",
+ "request": "launch",
+ "program": "${file}",
+ "cwd": "${fileDirname}",
+ "port": 9000
+ }
+ ]
+}
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 4274d76..6d293f2 100644
--- a/composer.json
+++ b/composer.json
@@ -12,11 +12,11 @@
],
"post-update-cmd": [
"setup\\Configuration::setup"
- ],
- "autoload": {
- "psr-4": {
- "SpidPHP\\": "src/"
- }
+ ]
+ },
+ "autoload": {
+ "psr-4": {
+ "SpidPHP\\": "src/"
}
}
}
diff --git a/composer.lock b/composer.lock
index 4a6f9a3..bedc328 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1,7 +1,7 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "d0f2b5c5b2a0656dd94e55792b743bdf",
@@ -12,12 +12,12 @@
"source": {
"type": "git",
"url": "https://github.com/onelogin/php-saml.git",
- "reference": "c98647228e5260004fe6bc31158f322ea94c152c"
+ "reference": "03efada0d2485268576a810834f2d61f9ff659aa"
},
"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/03efada0d2485268576a810834f2d61f9ff659aa",
+ "reference": "03efada0d2485268576a810834f2d61f9ff659aa",
"shasum": ""
},
"require": {
@@ -54,7 +54,7 @@
"onelogin",
"saml"
],
- "time": "2018-06-19T00:33:13+00:00"
+ "time": "2018-07-08T16:01:32+00:00"
},
{
"name": "robrichards/xmlseclibs",
@@ -263,7 +263,7 @@
},
{
"name": "symfony/yaml",
- "version": "v4.1.1",
+ "version": "v4.1.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
@@ -322,20 +322,21 @@
},
{
"name": "twig/twig",
- "version": "v2.4.8",
+ "version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
- "reference": "7b604c89da162034bdf4bb66310f358d313dd16d"
+ "reference": "6a5f676b77a90823c2d4eaf76137b771adf31323"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/7b604c89da162034bdf4bb66310f358d313dd16d",
- "reference": "7b604c89da162034bdf4bb66310f358d313dd16d",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/6a5f676b77a90823c2d4eaf76137b771adf31323",
+ "reference": "6a5f676b77a90823c2d4eaf76137b771adf31323",
"shasum": ""
},
"require": {
"php": "^7.0",
+ "symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
@@ -346,7 +347,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.4-dev"
+ "dev-master": "2.5-dev"
}
},
"autoload": {
@@ -375,16 +376,16 @@
},
{
"name": "Twig Team",
- "homepage": "http://twig.sensiolabs.org/contributors",
+ "homepage": "https://twig.symfony.com/contributors",
"role": "Contributors"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
- "homepage": "http://twig.sensiolabs.org",
+ "homepage": "https://twig.symfony.com",
"keywords": [
"templating"
],
- "time": "2018-04-02T09:24:19+00:00"
+ "time": "2018-07-13T07:18:09+00:00"
}
],
"packages-dev": [],
diff --git a/example/index.php b/example/index.php
index 48604af..a5abf56 100644
--- a/example/index.php
+++ b/example/index.php
@@ -3,27 +3,22 @@
/**
* SAML Handler
*/
-session_start();
-require_once("../vendor/autoload.php");
+require_once(__DIR__ . "/../vendor/autoload.php");
use SpidPHP\PhpSaml;
$settings = [
- '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',
- ),
+ 'spBaseUrl' => "BASE URL",
+ 'spEntityId' => "ENTITY ID",
+ 'spKeyFile' => __DIR__ . "/../sp.key",
+ 'spCrtFile' => __DIR__ . "/../sp.crt",
];
-$onelogin = new PhpSaml("http://idp.simevo.com", "/sp.key", "/sp.crt", $settings);
+ print_r($settings);
-if (!$onelogin->isAuthenticated()) $onelogin->login();
+$onelogin = new PhpSaml($settings);
+$onelogin->login("nome");
+//if (!$onelogin->isAuthenticated()) $onelogin->login();
-if ($onelogin->login()) $onelogin->logout();
+//if ($onelogin->login()) $onelogin->logout();
diff --git a/src/helper/ArrayHelper.php b/src/Helpers/ArrayHelper.php
similarity index 100%
rename from src/helper/ArrayHelper.php
rename to src/Helpers/ArrayHelper.php
diff --git a/src/helper/IdpHelper.php b/src/Helpers/IdpHelper.php
similarity index 91%
rename from src/helper/IdpHelper.php
rename to src/Helpers/IdpHelper.php
index 272b606..7fcea81 100644
--- a/src/helper/IdpHelper.php
+++ b/src/Helpers/IdpHelper.php
@@ -7,7 +7,7 @@ class IdpHelper
public static function getMetadata($idpName)
{
if (!file_exists("../config/idp/" . $idpName)) {
- throw new Exception("Invalid IDP Requested", 1);
+ throw new \Exception("Invalid IDP Requested", 1);
}
$xml = simplexml_load_file("../config/idp/" . $idpName . '.xml');
$metadata = array();
diff --git a/src/helper/SpHelper.php b/src/Helpers/SpHelper.php
similarity index 100%
rename from src/helper/SpHelper.php
rename to src/Helpers/SpHelper.php
diff --git a/src/PhpSaml.php b/src/PhpSaml.php
index 693cc8b..22267a4 100644
--- a/src/PhpSaml.php
+++ b/src/PhpSaml.php
@@ -1,5 +1,4 @@
mode = $mode;
$this->settings = $settings;
}
- private function initStrategy()
+ private function initStrategy($idpName)
{
switch ($this->mode) {
case 'onelogin':
- $this->phpSaml = new PhpSamlOneLogin($this->settings);
+ $this->phpSaml = new PhpSamlOneLogin($idpName, $this->settings);
break;
default:
- $this->phpSaml = new PhpSamlOneLogin($this->settings);
+ $this->phpSaml = new PhpSamlOneLogin($idpName, $this->settings);
break;
}
}
@@ -42,17 +35,21 @@ public function getSupportedIdps()
}
public function isAuthenticated()
- {
+ {
+ if (is_null($this->phpSaml)) return false;
$this->phpSaml->isAuthenticated();
}
public function login( $idpName, $redirectTo = null, $level = 1 )
{
- $this->phpSaml->login();
+ if (is_null($this->phpSaml)) $this->initStrategy($idpName);
+ die();
+ $this->phpSaml->login($redirectTo);
}
public function logout()
{
+ if (is_null($this->phpSaml)) return false;
$this->phpSaml->logout();
}
diff --git a/src/saml_strategy/PhpSamlInterface.php b/src/Strategy/Interfaces/PhpSamlInterface.php
similarity index 100%
rename from src/saml_strategy/PhpSamlInterface.php
rename to src/Strategy/Interfaces/PhpSamlInterface.php
diff --git a/src/saml_strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
similarity index 75%
rename from src/saml_strategy/PhpSamlOneLogin.php
rename to src/Strategy/PhpSamlOneLogin.php
index 60993cf..6df67fe 100644
--- a/src/saml_strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -13,38 +13,42 @@
class PhpSamlOneLogin implements PhpSamlInterface
{
-
- private $settings;
private $auth;
- function __construct($settings)
+ function __construct($idpName, $settings)
{
- $this->settings = $settings;
- $this->init($settings);
+ $this->init($idpName, $settings);
print_r($this->settings);
}
- private function init($idpName)
+ private function init($idpName, $settings)
{
$settingsHelper = new OneloginSamlConfig();
- if (!is_null($this->settings)) {
- $diff = ArrayHelper::array_diff_key_recursive($this->settings, get_object_vars($settingsHelper));
+ if (!is_null($settings)) {
+ $diff = ArrayHelper::array_diff_key_recursive($settings, get_object_vars($settingsHelper));
if (!empty($diff)) {
$message = "The following keys are invalid for the provided settings array: ";
- array_walk_recursive($diff, function ($v, $k) {
- $message .= $k . ", ";
- });
- throw new Exception($message, 1);
+ $first = true;
+ foreach ($diff as $key => $value) {
+ if ($first) $message .= $key;
+ $first = false;
+ $message .= ", " . $key;
+ }
+ throw new \Exception($message, 1);
}
- $settingsHelper->updateSettings($this->settings);
+ $settingsHelper->updateSettings($settings);
}
$settingsHelper->updateIdpMetadata($idpName);
$this->auth = new OneLogin_Saml2_Auth($settingsHelper->getSettings());
}
+ public function getSupportedIdps()
+ {
+ return array();
+ }
+
public function isAuthenticated()
{
- if (is_null($this->auth)) return false;
if ($auth->isAuthenticated) {
return false;
}
@@ -53,7 +57,6 @@ public function isAuthenticated()
public function login( $idpName, $redirectTo = null, $level = 1 )
{
- if (is_null($this->auth)) $this->init($idpName);
if ($auth->isAuthenticated) {
return false;
}
@@ -90,7 +93,6 @@ public function login( $idpName, $redirectTo = null, $level = 1 )
public function logout()
{
- if (is_null($this->auth)) return false;
if (!$auth->isAuthenticated()) {
return false;
}
diff --git a/src/config/OneloginSamlConfig.php b/src/config/OneloginSamlConfig.php
index 22137dc..4239951 100644
--- a/src/config/OneloginSamlConfig.php
+++ b/src/config/OneloginSamlConfig.php
@@ -9,19 +9,19 @@
class OneloginSamlConfig
{
// Default values SP
- private $spBaseUrl = '';
- private $spEntityId = null;
- private $spKeyFile = 'sp.key';
- private $spCrtFile = 'sp.crt';
+ var $spBaseUrl = '';
+ var $spEntityId = null;
+ var $spKeyFile = 'sp.key';
+ var $spCrtFile = 'sp.crt';
private $spKeyFileValue = null;
private $spCrtFileValue = null;
- private $spAcsUrl = null;
- private $spSloUrl = null;
+ var $spAcsUrl = null;
+ var $spSloUrl = null;
// Default values IDP
- private $idpEntityId = null;
- private $idpSSO = null;
- private $idpSLO = null;
- private $idpCertFile = null;
+ var $idpEntityId = null;
+ var $idpSSO = null;
+ var $idpSLO = null;
+ var $idpCertFile = null;
private $is_not_updatable = ['spKeyFileValue', 'spCrtFileValue', 'idpEntityId', 'idpSSO', 'idpSLO', 'idpCertFile'];
@@ -81,7 +81,7 @@ public function getSettings()
public function updateSettings($settings) {
foreach ($settings as $key => $value) {
// do not update idp os sp cert file values, they are updated in their own method
- if (!property_exists($key)) {
+ if (!property_exists(OneloginSamlConfig::class, $key)) {
continue;
}
if (in_array($key, $this->is_not_updatable)) {
@@ -92,7 +92,7 @@ public function updateSettings($settings) {
}
// 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 and .cert files is invalid", 1);
+ throw new \Exception("The path for .key and .cert files is invalid", 1);
}
$sp = SpHelper::getSpCert($this->spKeyFile, $this->spCrtFile);
$this->updateSpData($sp);
@@ -102,7 +102,7 @@ public function updateSettings($settings) {
public function updateIdpMetadata($idpName) {
$metadata = IdpHelper::getMetadata($idpName);
foreach ($metadata as $key => $value) {
- if (property_exists($key) && strpos("idp", $key) !== false) {
+ if (property_exists(OneloginSamlConfig::class, $key) && strpos("idp", $key) !== false) {
$this->{$key} = $value;
}
}
@@ -111,7 +111,7 @@ public function updateIdpMetadata($idpName) {
public function updateSpData($sp) {
if (!is_array($sp))
- throw new Exception("Invalid SP certificate data provided", 1);
+ throw new \Exception("Invalid SP certificate data provided", 1);
$this->spKeyFile = $sp['key'];
$this->spCrtFile = $sp['cert'];
From cf34f1a85d2be27058ed257810c2f8584ee0bb1b Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 26 Jul 2018 15:52:03 +0200
Subject: [PATCH 17/69] improved settings generation
---
example/index.php | 8 +++---
src/.DS_Store | Bin 0 -> 6148 bytes
src/Config/.DS_Store | Bin 0 -> 6148 bytes
src/Config/idp/.DS_Store | Bin 0 -> 6148 bytes
src/Config/idp/testenv2.xml | 39 ++++++++++++++++++++++++++++++
src/Helpers/IdpHelper.php | 13 +++++-----
src/Strategy/PhpSamlOneLogin.php | 3 ++-
src/config/OneloginSamlConfig.php | 8 +++---
8 files changed, 57 insertions(+), 14 deletions(-)
create mode 100644 src/.DS_Store
create mode 100644 src/Config/.DS_Store
create mode 100644 src/Config/idp/.DS_Store
create mode 100644 src/Config/idp/testenv2.xml
diff --git a/example/index.php b/example/index.php
index a5abf56..ef870d5 100644
--- a/example/index.php
+++ b/example/index.php
@@ -9,16 +9,18 @@
use SpidPHP\PhpSaml;
$settings = [
- 'spBaseUrl' => "BASE URL",
- 'spEntityId' => "ENTITY ID",
+ 'spBaseUrl' => "sp.simevo.com:8000",
+ 'spEntityId' => "sp.simevo.com:8000/metadata.php",
'spKeyFile' => __DIR__ . "/../sp.key",
'spCrtFile' => __DIR__ . "/../sp.crt",
+ 'spAcsUrl' => "sp.simevo.com:8000/index.php?acs",
+ 'spSloUrl' => "sp.simevo.com:8000/index.php?slo"
];
print_r($settings);
$onelogin = new PhpSaml($settings);
-$onelogin->login("nome");
+$onelogin->login("testenv2");
//if (!$onelogin->isAuthenticated()) $onelogin->login();
//if ($onelogin->login()) $onelogin->logout();
diff --git a/src/.DS_Store b/src/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..a500411ee3c77ad6f80303e03aa780d1f91ce863
GIT binary patch
literal 6148
zcmeHK!EVz)5S>j!x=Dq|0jWLug2W+0HKF2wDp_eO(OV@WH~?yGViHTPH;Nsi5>olX
zN5CKODSQE+18;Vhs!rh03qr6X&A!?3ytVhO<@FMg7|ez~QJ07$oUzeH^9$qa>}%Gr
znHEs!F;W^GXX;Iysd%m0CH_VQc$gvLCLEZX+Bi*ftuyRLXQ)g3sSaa`?R~WSo9zFyhnb2+4B~@-+$Qi_V)bc
zvMsmo`TNIb=NIo6AC{M&^fXA|h1GV);!pUDpf<^O;WW=wK0=;3oAi_t%4mXiO2xI;
zo#pxhzb@AnozNJyAw_f!)&s=o*IDA@3QMBC#OM*)ghq6+Qop@YkFGPPfK$LJa1#aW
zCs1zPgyd?S0#1SdLIM6hcyPwRVr5W&I?(7N0I-R)HpKiN#2n9JV6ifYD==ZGKtmPw
zh#?FedC%4b7Au2>PQo5OguSz{ClsOYj`2NRP9iYqTBm?hpsv7%>2`VlKl=UozfN*J
zr+`!7pHe_H55vO&reyclwaM{b>%q_9Y+P3vyrLk`TQO>RE8c-?L*C;67+9J%rYLs$C0eK|*&5UQf>*tldLqwuC%|fC!5lJ-0S`*zJ!sFalq~<&g
zpx`<5=d{o%ES}EGzrX?cX*=Ui>y<7UH7P*<|E)`DZ#R@=3Y5`AgL5
zjeGYWNZFFDN3BosP|xBrDW{WOGCpK$KPiW)(?4ik+~`SqkoRZD?I$~0l}WDpW0Ra`
zeS{o+%vGjmJv~*~#LN@h0V$iZdEDNZ&%19r!RxTQ=mhgH?7r#*TU+5`(Ui}ghi~^z
zPS3y2zb(H1usb2}ks5jI@ER_lxaFP2V^wH1fQO@>(tA?Wr-C#MK$D`F5;}#w1COFF
z@D1oCjcB++;3e{J6A06bXTUSy8CVYn+;J!$uE*>6x9|*j2G)oHJ|6-!#>io1(HtG<
zObGzw-$*0S&CfqDUItlY+%;TOcT!kWB
z=^+9WP9n1Cd(VJpV3~osHQRjuzx#9jzntVP&wyv(zhXc%cH`Y1mgMf%mBsO08=#$_
qv2a{v@g@a|xr!0XSMdg#5%>dEfRV$>B0LcPBVcIoooC>$GH?Z3B5R)j
literal 0
HcmV?d00001
diff --git a/src/Config/idp/.DS_Store b/src/Config/idp/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..505157fb3008733e968f85caab1c60219c19f558
GIT binary patch
literal 6148
zcmeHKyH3ME5S)b+k)TLPc_kGRe8DLS1vNi_0(6EH1VrhIf8j6qGnjn{6d4*M8Z;~I
z&fR*)XHVhv0#lzJ6y8FcTDq}=C?{SNJJmCx{c%D>$pK$IWwq!m;
z{NmqXxEMCq>tVBIjX&Tk{rEkME149K0#ZNX}$M^Th@&DXr%3&+HuGaq!Keg<3@nH2bI1wH^OHXL>U
literal 0
HcmV?d00001
diff --git a/src/Config/idp/testenv2.xml b/src/Config/idp/testenv2.xml
new file mode 100644
index 0000000..1030cb0
--- /dev/null
+++ b/src/Config/idp/testenv2.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+ MIIDiDCCAnCgAwIBAgIJAJnqANY7GvtNMA0GCSqGSIb3DQEBCwUAMFkxCzAJBgNV
+ BAYTAklUMQ4wDAYDVQQIDAVJdGFseTENMAsGA1UEBwwEUm9tZTERMA8GA1UECgwI
+ dGVzdGVudjIxGDAWBgNVBAMMDyR7YW5zaWJsZV9mcWRufTAeFw0xODA3MTkxMzEw
+ MDVaFw0xOTA3MTkxMzEwMDVaMFkxCzAJBgNVBAYTAklUMQ4wDAYDVQQIDAVJdGFs
+ eTENMAsGA1UEBwwEUm9tZTERMA8GA1UECgwIdGVzdGVudjIxGDAWBgNVBAMMDyR7
+ YW5zaWJsZV9mcWRufTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALTP
+ ycItk7xvubL0WgegvbtCvhzeCq13WorzjYQdpWvUwY8YmL51h6ssKfWMfnSj96Ix
+ lJw2HTm+TgHK2/S7Iw7gh6xoaY+LDmkZGJKzUSFR/Hn7WbFNb3jytowiNDQdcBZd
+ hNhEnDvd2fLMGxD81qdlMx3y5XHP+p9Gc8bjp8aShGw+DQpWBXcfoDnCXz5ywmnR
+ oD66CnMFMQXmD0wZf79/0fY+Muwn83r7P0h6bJCFDjPdGiSeo7q5AJKkERoNoedc
+ HThCuT0uN36bDaVBIcSxVtPjvVhfcNIVN5JHaCLZT89aU8DAJlTUiO3u5Nj4aDjD
+ XAhxMWkwGbHXCznhjVMCAwEAAaNTMFEwHQYDVR0OBBYEFH1/ReU+04oYtVpMgD/z
+ VCPuagu6MB8GA1UdIwQYMBaAFH1/ReU+04oYtVpMgD/zVCPuagu6MA8GA1UdEwEB
+ /wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAWT9+r+ojVmxUUZvq8/TumEX9Y0
+ FxxQebTcPMeumA58mp9kDCeNK73PZ6cbQSGXzwbNmHw48N2kZMl3rS8ddYPG3nFx
+ EZO5Xi0De2SLGwLZX43lfD4BHhhqhTlnBK8cL+LvySQ32X1vL8aKly/UTez3/DCr
+ dTqFjp1V0PdY2q0Ni3UAiO90MpFGbP+aAQ1LGtI0EWpDCVAqqgAA2EA+s0AlwbC5
+ cuDbQUjHA5dhkWT/4kvHB/E5zPZUtRV4d3mYBs33lfIyKXWjjgR4T8j01wMk2LWC
+ nBU8i4mCb1w3v94KcRbnK23bJLz+zNp6I3belhLknSahyjKPl+6FBSyW/GE=
+
+
+
+
+
+
+
+ urn:oasis:names:tc:SAML:2.0:nameid-format:transient
+
+
+
+
+
diff --git a/src/Helpers/IdpHelper.php b/src/Helpers/IdpHelper.php
index 7fcea81..ed5fd6f 100644
--- a/src/Helpers/IdpHelper.php
+++ b/src/Helpers/IdpHelper.php
@@ -6,15 +6,16 @@ class IdpHelper
{
public static function getMetadata($idpName)
{
- if (!file_exists("../config/idp/" . $idpName)) {
+ if (!file_exists(__DIR__ . "/../config/idp/" . $idpName . ".xml")) {
throw new \Exception("Invalid IDP Requested", 1);
}
- $xml = simplexml_load_file("../config/idp/" . $idpName . '.xml');
+ $xml = simplexml_load_file(__DIR__ . "/../config/idp/" . $idpName . '.xml');
+
$metadata = array();
- $metadata['idp_entityid'] = $xml->xpath('//ns0:EntityDescriptor/@entityID')[0];
- $metadata['idp_sso'] = $xml->xpath('//ns0:SingleSignOnService/@Location')[0];
- $metadata['idp_slo'] = $xml->xpath('//ns0:SingleLogoutService/@Location')[0];
- $metadata['idp_cert'] = $xml->xpath('//ns1:X509Certificate')[0];
+ $metadata['idpEntityId'] = $xml->attributes()->entityID;
+ $metadata['idpSSO'] = $xml->xpath('//SingleSignOnService')[0]->attributes()->Location;
+ $metadata['idpSLO'] = $xml->xpath('//SingleLogoutService')[0]->attributes()->Location;
+ $metadata['idpCertValue'] = $xml->xpath('//X509Certificate')[0];
return $metadata;
}
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 6df67fe..5f38208 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -39,7 +39,8 @@ private function init($idpName, $settings)
$settingsHelper->updateSettings($settings);
}
$settingsHelper->updateIdpMetadata($idpName);
- $this->auth = new OneLogin_Saml2_Auth($settingsHelper->getSettings());
+ print_r($settingsHelper->getSettings()); die();
+ $this->auth = new Auth($settingsHelper->getSettings());
}
public function getSupportedIdps()
diff --git a/src/config/OneloginSamlConfig.php b/src/config/OneloginSamlConfig.php
index 4239951..dfc452f 100644
--- a/src/config/OneloginSamlConfig.php
+++ b/src/config/OneloginSamlConfig.php
@@ -21,9 +21,9 @@ class OneloginSamlConfig
var $idpEntityId = null;
var $idpSSO = null;
var $idpSLO = null;
- var $idpCertFile = null;
+ var $idpCertValue = null;
- private $is_not_updatable = ['spKeyFileValue', 'spCrtFileValue', 'idpEntityId', 'idpSSO', 'idpSLO', 'idpCertFile'];
+ private $is_not_updatable = ['spKeyFileValue', 'spCrtFileValue', 'idpEntityId', 'idpSSO', 'idpSLO', 'idpCertValue'];
function __construct()
{
@@ -65,7 +65,7 @@ public function getSettings()
'singleLogoutService' => array(
'url' => $this->idpSLO,
),
- 'x509cert' => $this->idpCertFile,
+ 'x509cert' => $this->idpCertValue,
),
'security' => array(
'authnRequestsSigned' => true,
@@ -102,7 +102,7 @@ public function updateSettings($settings) {
public function updateIdpMetadata($idpName) {
$metadata = IdpHelper::getMetadata($idpName);
foreach ($metadata as $key => $value) {
- if (property_exists(OneloginSamlConfig::class, $key) && strpos("idp", $key) !== false) {
+ if (property_exists(OneloginSamlConfig::class, $key) && strpos($key, "idp") !== false) {
$this->{$key} = $value;
}
}
From af5b721203fb96e8674d88777b09aed00a166075 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 26 Jul 2018 16:00:07 +0200
Subject: [PATCH 18/69] fix variable references
---
example/index.php | 10 +++++-----
src/PhpSaml.php | 1 -
src/Strategy/PhpSamlOneLogin.php | 28 +++++++++++++---------------
3 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/example/index.php b/example/index.php
index ef870d5..c6d46a8 100644
--- a/example/index.php
+++ b/example/index.php
@@ -7,14 +7,14 @@
require_once(__DIR__ . "/../vendor/autoload.php");
use SpidPHP\PhpSaml;
-
+$base = "http://sp.simevo.com:8000";
$settings = [
- 'spBaseUrl' => "sp.simevo.com:8000",
- 'spEntityId' => "sp.simevo.com:8000/metadata.php",
+ 'spBaseUrl' => $base,
+ 'spEntityId' => $base."/metadata.php",
'spKeyFile' => __DIR__ . "/../sp.key",
'spCrtFile' => __DIR__ . "/../sp.crt",
- 'spAcsUrl' => "sp.simevo.com:8000/index.php?acs",
- 'spSloUrl' => "sp.simevo.com:8000/index.php?slo"
+ 'spAcsUrl' => $base."/index.php?acs",
+ 'spSloUrl' => $base."/index.php?slo"
];
print_r($settings);
diff --git a/src/PhpSaml.php b/src/PhpSaml.php
index 22267a4..db35c4c 100644
--- a/src/PhpSaml.php
+++ b/src/PhpSaml.php
@@ -43,7 +43,6 @@ public function isAuthenticated()
public function login( $idpName, $redirectTo = null, $level = 1 )
{
if (is_null($this->phpSaml)) $this->initStrategy($idpName);
- die();
$this->phpSaml->login($redirectTo);
}
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 5f38208..7a12c38 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -18,7 +18,6 @@ class PhpSamlOneLogin implements PhpSamlInterface
function __construct($idpName, $settings)
{
$this->init($idpName, $settings);
- print_r($this->settings);
}
private function init($idpName, $settings)
@@ -39,7 +38,6 @@ private function init($idpName, $settings)
$settingsHelper->updateSettings($settings);
}
$settingsHelper->updateIdpMetadata($idpName);
- print_r($settingsHelper->getSettings()); die();
$this->auth = new Auth($settingsHelper->getSettings());
}
@@ -58,32 +56,32 @@ public function isAuthenticated()
public function login( $idpName, $redirectTo = null, $level = 1 )
{
- if ($auth->isAuthenticated) {
+ if ($this->auth->isAuthenticated) {
return false;
}
- $auth->login();
+ $this->auth->login();
$requestID = null;
if (isset($_SESSION['AuthNRequestID'])) {
$requestID = $_SESSION['AuthNRequestID'];
}
- $auth->processResponse($requestID);
+ $this->auth->processResponse($requestID);
unset($_SESSION['AuthNRequestID']);
- $errors = $auth->getErrors();
+ $errors = $this->auth->getErrors();
if (!empty($errors)) {
return $errors;
}
- if (!$auth->isAuthenticated()) {
+ if (!$this->auth->isAuthenticated()) {
return false;
}
- $_SESSION['samlUserdata'] = $auth->getAttributes();
- $_SESSION['samlNameId'] = $auth->getNameId();
- $_SESSION['samlNameIdFormat'] = $auth->getNameIdFormat();
- $_SESSION['samlSessionIndex'] = $auth->getSessionIndex();
+ $_SESSION['samlUserdata'] = $this->auth->getAttributes();
+ $_SESSION['samlNameId'] = $this->auth->getNameId();
+ $_SESSION['samlNameIdFormat'] = $this->auth->getNameIdFormat();
+ $_SESSION['samlSessionIndex'] = $this->auth->getSessionIndex();
if (!empty($_SESSION['samlUserdata'])) {
return true;
@@ -94,13 +92,13 @@ public function login( $idpName, $redirectTo = null, $level = 1 )
public function logout()
{
- if (!$auth->isAuthenticated()) {
+ if (!$this->auth->isAuthenticated()) {
return false;
}
- $auth->logout();
- $auth->processSLO();
+ $this->auth->logout();
+ $this->auth->processSLO();
- $errors = $auth->getErrors();
+ $errors = $this->auth->getErrors();
if (!empty($errors)) {
return $errors;
}
From 7edd48371509269bdcea5bee245a41a71ab1bfc8 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 26 Jul 2018 16:16:13 +0200
Subject: [PATCH 19/69] fixed xml parsing
---
example/index.php | 6 +++---
src/Helpers/IdpHelper.php | 8 ++++----
src/PhpSaml.php | 2 +-
src/Strategy/Interfaces/PhpSamlInterface.php | 2 +-
src/Strategy/PhpSamlOneLogin.php | 9 +++++----
5 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/example/index.php b/example/index.php
index c6d46a8..2f02790 100644
--- a/example/index.php
+++ b/example/index.php
@@ -17,10 +17,10 @@
'spSloUrl' => $base."/index.php?slo"
];
- print_r($settings);
-
$onelogin = new PhpSaml($settings);
-$onelogin->login("testenv2");
+$result = $onelogin->login("testenv2");
+
+var_dump($result);
//if (!$onelogin->isAuthenticated()) $onelogin->login();
//if ($onelogin->login()) $onelogin->logout();
diff --git a/src/Helpers/IdpHelper.php b/src/Helpers/IdpHelper.php
index ed5fd6f..44bf76c 100644
--- a/src/Helpers/IdpHelper.php
+++ b/src/Helpers/IdpHelper.php
@@ -12,10 +12,10 @@ public static function getMetadata($idpName)
$xml = simplexml_load_file(__DIR__ . "/../config/idp/" . $idpName . '.xml');
$metadata = array();
- $metadata['idpEntityId'] = $xml->attributes()->entityID;
- $metadata['idpSSO'] = $xml->xpath('//SingleSignOnService')[0]->attributes()->Location;
- $metadata['idpSLO'] = $xml->xpath('//SingleLogoutService')[0]->attributes()->Location;
- $metadata['idpCertValue'] = $xml->xpath('//X509Certificate')[0];
+ $metadata['idpEntityId'] = $xml->attributes()->entityID->__toString();
+ $metadata['idpSSO'] = $xml->xpath('//SingleSignOnService')[0]->attributes()->Location->__toString();
+ $metadata['idpSLO'] = $xml->xpath('//SingleLogoutService')[0]->attributes()->Location->__toString();
+ $metadata['idpCertValue'] = $xml->xpath('//X509Certificate')[0]->__toString();
return $metadata;
}
diff --git a/src/PhpSaml.php b/src/PhpSaml.php
index db35c4c..2f7a977 100644
--- a/src/PhpSaml.php
+++ b/src/PhpSaml.php
@@ -40,7 +40,7 @@ public function isAuthenticated()
$this->phpSaml->isAuthenticated();
}
- public function login( $idpName, $redirectTo = null, $level = 1 )
+ public function login( $idpName, $redirectTo = '', $level = 1 )
{
if (is_null($this->phpSaml)) $this->initStrategy($idpName);
$this->phpSaml->login($redirectTo);
diff --git a/src/Strategy/Interfaces/PhpSamlInterface.php b/src/Strategy/Interfaces/PhpSamlInterface.php
index e12b173..1bb6b7b 100644
--- a/src/Strategy/Interfaces/PhpSamlInterface.php
+++ b/src/Strategy/Interfaces/PhpSamlInterface.php
@@ -5,6 +5,6 @@
interface PhpSamlInterface {
public function getSupportedIdps();
public function isAuthenticated();
- public function login( $idpName, $redirectTo = null, $level = 1 );
+ public function login( $idpName, $redirectTo = '', $level = 1 );
public function logout();
}
\ No newline at end of file
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 7a12c38..2dd669b 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -54,13 +54,14 @@ public function isAuthenticated()
return true;
}
- public function login( $idpName, $redirectTo = null, $level = 1 )
+ public function login( $idpName, $redirectTo = '', $level = 1 )
{
- if ($this->auth->isAuthenticated) {
+ if ($this->auth->isAuthenticated()) {
return false;
}
- $this->auth->login();
-
+
+ $this->auth->login($redirectTo);
+
$requestID = null;
if (isset($_SESSION['AuthNRequestID'])) {
$requestID = $_SESSION['AuthNRequestID'];
From 991d6e1171735b4695ba413367d78f42e29eb247 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 26 Jul 2018 18:18:01 +0200
Subject: [PATCH 20/69] WIP: sp metadata generation
---
.DS_Store | Bin 8196 -> 8196 bytes
example/index.php | 9 +--
example/metadata.php | 25 +++++++++
src/{PhpSaml.php => SpidPHP.php} | 11 +++-
src/Strategy/Interfaces/PhpSamlInterface.php | 1 +
src/Strategy/PhpSamlOneLogin.php | 55 ++++++++++++++++---
6 files changed, 86 insertions(+), 15 deletions(-)
create mode 100644 example/metadata.php
rename src/{PhpSaml.php => SpidPHP.php} (82%)
diff --git a/.DS_Store b/.DS_Store
index 2137870ec5135ccb2df51ce4b88d941bb650d631..207e9eb093e9c48a6ed10101cd775d66007a764f 100644
GIT binary patch
delta 43
zcmZp1XmOa}&nUJrU^hRb*km37*UjYu6WAv=
delta 65
zcmZp1XmOa}&nUhzU^hRb_+%adS8-;BB!*0eJkOl` $base,
@@ -17,10 +17,11 @@
'spSloUrl' => $base."/index.php?slo"
];
-$onelogin = new PhpSaml($settings);
-$result = $onelogin->login("testenv2");
+$onelogin = new SpidPHP($settings);
+//$result = $onelogin->login("testenv2");
+
+$metadata = $onelogin->getSPMetadata();
-var_dump($result);
//if (!$onelogin->isAuthenticated()) $onelogin->login();
//if ($onelogin->login()) $onelogin->logout();
diff --git a/example/metadata.php b/example/metadata.php
new file mode 100644
index 0000000..45199b5
--- /dev/null
+++ b/example/metadata.php
@@ -0,0 +1,25 @@
+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();
+}
\ No newline at end of file
diff --git a/src/PhpSaml.php b/src/SpidPHP.php
similarity index 82%
rename from src/PhpSaml.php
rename to src/SpidPHP.php
index 2f7a977..96ecf93 100644
--- a/src/PhpSaml.php
+++ b/src/SpidPHP.php
@@ -4,7 +4,7 @@
use SpidPHP\Strategy\Interfaces\PhpSamlInterface;
use SpidPHP\Strategy\PhpSamlOneLogin;
-class PhpSaml implements PhpSamlInterface
+class SpidPHP implements PhpSamlInterface
{
private $phpSaml = null;
@@ -17,7 +17,7 @@ public function __construct($settings = null, $mode = 'onelogin')
$this->settings = $settings;
}
- private function initStrategy($idpName)
+ private function initStrategy($idpName = null)
{
switch ($this->mode) {
case 'onelogin':
@@ -29,6 +29,12 @@ private function initStrategy($idpName)
}
}
+ public function getSPMetadata()
+ {
+ if (is_null($this->phpSaml)) $this->initStrategy();
+ $this->phpSaml->getSPMetadata();
+ }
+
public function getSupportedIdps()
{
return array();
@@ -43,6 +49,7 @@ public function isAuthenticated()
public function login( $idpName, $redirectTo = '', $level = 1 )
{
if (is_null($this->phpSaml)) $this->initStrategy($idpName);
+ return;
$this->phpSaml->login($redirectTo);
}
diff --git a/src/Strategy/Interfaces/PhpSamlInterface.php b/src/Strategy/Interfaces/PhpSamlInterface.php
index 1bb6b7b..aaa496d 100644
--- a/src/Strategy/Interfaces/PhpSamlInterface.php
+++ b/src/Strategy/Interfaces/PhpSamlInterface.php
@@ -3,6 +3,7 @@
namespace SpidPHP\Strategy\Interfaces;
interface PhpSamlInterface {
+ public function getSPMetadata();
public function getSupportedIdps();
public function isAuthenticated();
public function login( $idpName, $redirectTo = '', $level = 1 );
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 2dd669b..e8c660f 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -10,21 +10,30 @@
use OneLogin\Saml2\Auth;
use OneLogin\Saml2\Utils;
+use OneLogin\Saml2\Settings;
class PhpSamlOneLogin implements PhpSamlInterface
{
+ private $idpName = null;
+ private $settings = null;
+
private $auth;
+ private $settingsHelper;
+ private $oneloginSettings;
- function __construct($idpName, $settings)
+ function __construct($idpName = null, $settings)
{
- $this->init($idpName, $settings);
+ $this->idpName = $idpName ?? "testenv2";
+ $this->settings = $settings;
+ $this->init();
}
- private function init($idpName, $settings)
+ private function init()
{
$settingsHelper = new OneloginSamlConfig();
- if (!is_null($settings)) {
- $diff = ArrayHelper::array_diff_key_recursive($settings, get_object_vars($settingsHelper));
+ $this->settingsHelper = $settingsHelper;
+ if (!is_null($this->settings)) {
+ $diff = ArrayHelper::array_diff_key_recursive($this->settings, get_object_vars($settingsHelper));
if (!empty($diff)) {
$message = "The following keys are invalid for the provided settings array: ";
$first = true;
@@ -35,10 +44,36 @@ private function init($idpName, $settings)
}
throw new \Exception($message, 1);
}
- $settingsHelper->updateSettings($settings);
+ $settingsHelper->updateSettings($this->settings);
+ }
+
+ $this->settingsHelper->updateIdpMetadata($this->idpName);
+ $this->settings = new Settings($this->settingsHelper->getSettings());
+ $this->auth = new Auth($this->settingsHelper->getSettings());
+ }
+
+ private function rebuildPhpSamlOnelogin($idpName)
+ {
+ if ($this->idpName != $idpName) {
+ $this->idpName = $idpName;
+ $this->init();
}
- $settingsHelper->updateIdpMetadata($idpName);
- $this->auth = new Auth($settingsHelper->getSettings());
+ }
+
+ public function getSPMetadata()
+ {
+ $oneloginSettings = new Settings($this->settings->getSettings());
+ $metadata = $oneloginSettings->getSPMetadata();
+ var_dump($oneloginSettings);
+ die();
+ $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()
@@ -48,7 +83,7 @@ public function getSupportedIdps()
public function isAuthenticated()
{
- if ($auth->isAuthenticated) {
+ if ($this->auth->isAuthenticated) {
return false;
}
return true;
@@ -56,6 +91,8 @@ public function isAuthenticated()
public function login( $idpName, $redirectTo = '', $level = 1 )
{
+ $this->rebuildPhpSamlOnelogin($idpName);
+
if ($this->auth->isAuthenticated()) {
return false;
}
From adecf84d42226c165060d1660fd192d99d91a447 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 27 Jul 2018 09:53:25 +0200
Subject: [PATCH 21/69] fixed SP metadata generation
---
src/SpidPHP.php | 1 -
src/Strategy/PhpSamlOneLogin.php | 4 ++--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/SpidPHP.php b/src/SpidPHP.php
index 96ecf93..fbc8ea9 100644
--- a/src/SpidPHP.php
+++ b/src/SpidPHP.php
@@ -49,7 +49,6 @@ public function isAuthenticated()
public function login( $idpName, $redirectTo = '', $level = 1 )
{
if (is_null($this->phpSaml)) $this->initStrategy($idpName);
- return;
$this->phpSaml->login($redirectTo);
}
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index e8c660f..263232a 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -62,9 +62,9 @@ private function rebuildPhpSamlOnelogin($idpName)
public function getSPMetadata()
{
- $oneloginSettings = new Settings($this->settings->getSettings());
+ $oneloginSettings = new Settings($this->settingsHelper->getSettings());
$metadata = $oneloginSettings->getSPMetadata();
- var_dump($oneloginSettings);
+ var_dump($metadata);
die();
$errors = $oneloginSettings->validateMetadata($metadata);
if (!empty($errors)) {
From 1a806c6dd10d84e4861e9986c7207fd21fed15dc Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 27 Jul 2018 12:02:47 +0200
Subject: [PATCH 22/69] fixed methods return data
---
example/index.php | 4 +++-
src/SpidPHP.php | 8 ++++----
src/Strategy/PhpSamlOneLogin.php | 3 +--
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/example/index.php b/example/index.php
index c777a34..efe645d 100644
--- a/example/index.php
+++ b/example/index.php
@@ -7,7 +7,7 @@
require_once(__DIR__ . "/../vendor/autoload.php");
use SpidPHP\SpidPHP;
-$base = "http://sp.simevo.com:8000";
+$base = "http://spid.test.com";
$settings = [
'spBaseUrl' => $base,
'spEntityId' => $base."/metadata.php",
@@ -22,6 +22,8 @@
$metadata = $onelogin->getSPMetadata();
+header('Content-Type: text/xml');
+echo $metadata;
//if (!$onelogin->isAuthenticated()) $onelogin->login();
//if ($onelogin->login()) $onelogin->logout();
diff --git a/src/SpidPHP.php b/src/SpidPHP.php
index fbc8ea9..194fae0 100644
--- a/src/SpidPHP.php
+++ b/src/SpidPHP.php
@@ -32,7 +32,7 @@ private function initStrategy($idpName = null)
public function getSPMetadata()
{
if (is_null($this->phpSaml)) $this->initStrategy();
- $this->phpSaml->getSPMetadata();
+ return $this->phpSaml->getSPMetadata();
}
public function getSupportedIdps()
@@ -43,19 +43,19 @@ public function getSupportedIdps()
public function isAuthenticated()
{
if (is_null($this->phpSaml)) return false;
- $this->phpSaml->isAuthenticated();
+ return $this->phpSaml->isAuthenticated();
}
public function login( $idpName, $redirectTo = '', $level = 1 )
{
if (is_null($this->phpSaml)) $this->initStrategy($idpName);
- $this->phpSaml->login($redirectTo);
+ return $this->phpSaml->login($redirectTo);
}
public function logout()
{
if (is_null($this->phpSaml)) return false;
- $this->phpSaml->logout();
+ return $this->phpSaml->logout();
}
}
\ No newline at end of file
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 263232a..5d55062 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -64,8 +64,7 @@ public function getSPMetadata()
{
$oneloginSettings = new Settings($this->settingsHelper->getSettings());
$metadata = $oneloginSettings->getSPMetadata();
- var_dump($metadata);
- die();
+
$errors = $oneloginSettings->validateMetadata($metadata);
if (!empty($errors)) {
throw new OneLogin_Saml2_Error(
From 98f3a20d2ba4dbac37d200e40dbb9a4886c7f650 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 27 Jul 2018 12:20:00 +0200
Subject: [PATCH 23/69] removed useless dependencies and fix case sensitive
names
---
composer.json | 2 --
src/Helpers/IdpHelper.php | 4 ++--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/composer.json b/composer.json
index 6d293f2..d0d694a 100644
--- a/composer.json
+++ b/composer.json
@@ -1,8 +1,6 @@
{
"require": {
"onelogin/php-saml": "3.0.0.x-dev",
- "twig/twig": "^2.4",
- "symfony/yaml": "^4.1",
"squizlabs/php_codesniffer": "*"
},
diff --git a/src/Helpers/IdpHelper.php b/src/Helpers/IdpHelper.php
index 44bf76c..443d093 100644
--- a/src/Helpers/IdpHelper.php
+++ b/src/Helpers/IdpHelper.php
@@ -6,10 +6,10 @@ class IdpHelper
{
public static function getMetadata($idpName)
{
- if (!file_exists(__DIR__ . "/../config/idp/" . $idpName . ".xml")) {
+ if (!file_exists(__DIR__ . "/../Config/idp/" . $idpName . ".xml")) {
throw new \Exception("Invalid IDP Requested", 1);
}
- $xml = simplexml_load_file(__DIR__ . "/../config/idp/" . $idpName . '.xml');
+ $xml = simplexml_load_file(__DIR__ . "/../Config/idp/" . $idpName . '.xml');
$metadata = array();
$metadata['idpEntityId'] = $xml->attributes()->entityID->__toString();
From c005a207691d3410391252d75a06b2cd398831ea Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 27 Jul 2018 12:28:11 +0200
Subject: [PATCH 24/69] removed session in login
---
example/index.php | 9 +++-----
example/metadata.php | 37 ++++++++++++++------------------
example/settings.php | 0
src/Strategy/PhpSamlOneLogin.php | 16 +++++++-------
4 files changed, 27 insertions(+), 35 deletions(-)
create mode 100644 example/settings.php
diff --git a/example/index.php b/example/index.php
index efe645d..fae6339 100644
--- a/example/index.php
+++ b/example/index.php
@@ -5,9 +5,10 @@
*/
require_once(__DIR__ . "/../vendor/autoload.php");
+require_once(__DIR__ . "/settings.php");
use SpidPHP\SpidPHP;
-$base = "http://spid.test.com";
+$base = "http://sp.simevo.com:8000";
$settings = [
'spBaseUrl' => $base,
'spEntityId' => $base."/metadata.php",
@@ -18,12 +19,8 @@
];
$onelogin = new SpidPHP($settings);
-//$result = $onelogin->login("testenv2");
+$result = $onelogin->login("testenv2");
-$metadata = $onelogin->getSPMetadata();
-
-header('Content-Type: text/xml');
-echo $metadata;
//if (!$onelogin->isAuthenticated()) $onelogin->login();
//if ($onelogin->login()) $onelogin->logout();
diff --git a/example/metadata.php b/example/metadata.php
index 45199b5..374fc15 100644
--- a/example/metadata.php
+++ b/example/metadata.php
@@ -1,25 +1,20 @@
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();
-}
\ No newline at end of file
+require_once(__DIR__ . "/../vendor/autoload.php");
+require_once(__DIR__ . "/settings.php");
+
+use SpidPHP\SpidPHP;
+
+$onelogin = new SpidPHP($settings);
+
+$metadata = $onelogin->getSPMetadata();
+
+header('Content-Type: text/xml');
+echo $metadata;
+//if (!$onelogin->isAuthenticated()) $onelogin->login();
+
+//if ($onelogin->login()) $onelogin->logout();
diff --git a/example/settings.php b/example/settings.php
new file mode 100644
index 0000000..e69de29
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 5d55062..b5119bb 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -114,14 +114,14 @@ public function login( $idpName, $redirectTo = '', $level = 1 )
if (!$this->auth->isAuthenticated()) {
return false;
}
-
- $_SESSION['samlUserdata'] = $this->auth->getAttributes();
- $_SESSION['samlNameId'] = $this->auth->getNameId();
- $_SESSION['samlNameIdFormat'] = $this->auth->getNameIdFormat();
- $_SESSION['samlSessionIndex'] = $this->auth->getSessionIndex();
-
- if (!empty($_SESSION['samlUserdata'])) {
- return true;
+ $data = array();
+ $data['samlUserdata'] = $this->auth->getAttributes();
+ $data['samlNameId'] = $this->auth->getNameId();
+ $data['samlNameIdFormat'] = $this->auth->getNameIdFormat();
+ $data['samlSessionIndex'] = $this->auth->getSessionIndex();
+
+ if (!empty($data['samlUserdata'])) {
+ return $data;
}
return false;
From 43f8f67bbce65e9e405d4b25a83f880211b9434e Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 27 Jul 2018 13:59:00 +0200
Subject: [PATCH 25/69] saving userdata in class instance
---
example/index.php | 88 ++++++++++++++++++++++++++++++++
example/settings.php | 11 ++++
src/Strategy/PhpSamlOneLogin.php | 11 ++--
3 files changed, 105 insertions(+), 5 deletions(-)
diff --git a/example/index.php b/example/index.php
index fae6339..5395740 100644
--- a/example/index.php
+++ b/example/index.php
@@ -24,3 +24,91 @@
//if (!$onelogin->isAuthenticated()) $onelogin->login();
//if ($onelogin->login()) $onelogin->logout();
+
+
+
+if (isset($_GET['sso'])) {
+ $result = $onelogin->login("testenv2");
+ print_r($result);
+} 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 'Name | Values | ';
+ foreach ($attributes as $attributeName => $attributeValues) {
+ echo '' . htmlentities($attributeName) . ' | ';
+ foreach ($attributeValues as $attributeValue) {
+ echo '- ' . htmlentities($attributeValue) . '
';
+ }
+ echo ' |
';
+ }
+ 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/example/settings.php b/example/settings.php
index e69de29..4a0cd20 100644
--- a/example/settings.php
+++ b/example/settings.php
@@ -0,0 +1,11 @@
+ $base,
+ 'spEntityId' => $base."/metadata.php",
+ 'spKeyFile' => __DIR__ . "/../sp.key",
+ 'spCrtFile' => __DIR__ . "/../sp.crt",
+ 'spAcsUrl' => $base."/index.php?acs",
+ 'spSloUrl' => $base."/index.php?slo"
+ ];
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index b5119bb..8b0ed6f 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -20,6 +20,7 @@ class PhpSamlOneLogin implements PhpSamlInterface
private $auth;
private $settingsHelper;
private $oneloginSettings;
+ private $userdata;
function __construct($idpName = null, $settings)
{
@@ -114,11 +115,11 @@ public function login( $idpName, $redirectTo = '', $level = 1 )
if (!$this->auth->isAuthenticated()) {
return false;
}
- $data = array();
- $data['samlUserdata'] = $this->auth->getAttributes();
- $data['samlNameId'] = $this->auth->getNameId();
- $data['samlNameIdFormat'] = $this->auth->getNameIdFormat();
- $data['samlSessionIndex'] = $this->auth->getSessionIndex();
+ $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();
if (!empty($data['samlUserdata'])) {
return $data;
From 85a15024183dceb2dfc7de4ef9dfef65c2209943 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 27 Jul 2018 14:53:09 +0200
Subject: [PATCH 26/69] fix login idp
---
example/index.php | 47 ++++++++++----------------------
src/Helpers/IdpHelper.php | 3 +-
src/SpidPHP.php | 2 +-
src/Strategy/PhpSamlOneLogin.php | 4 +--
4 files changed, 19 insertions(+), 37 deletions(-)
diff --git a/example/index.php b/example/index.php
index 5395740..a37ff2c 100644
--- a/example/index.php
+++ b/example/index.php
@@ -8,51 +8,31 @@
require_once(__DIR__ . "/settings.php");
use SpidPHP\SpidPHP;
-$base = "http://sp.simevo.com:8000";
-$settings = [
- 'spBaseUrl' => $base,
- 'spEntityId' => $base."/metadata.php",
- 'spKeyFile' => __DIR__ . "/../sp.key",
- 'spCrtFile' => __DIR__ . "/../sp.crt",
- 'spAcsUrl' => $base."/index.php?acs",
- 'spSloUrl' => $base."/index.php?slo"
- ];
+
+
+echo 'Login
';
+echo 'Login and access to attrs.php page
';
+echo 'Show the SP metadata
';
$onelogin = new SpidPHP($settings);
-$result = $onelogin->login("testenv2");
+
+if (isset($_GET['sso'])) {
+ $result = $onelogin->login("testenv2");
+ print_r($result);
+ die();
+}
//if (!$onelogin->isAuthenticated()) $onelogin->login();
//if ($onelogin->login()) $onelogin->logout();
-
+/*
if (isset($_GET['sso'])) {
$result = $onelogin->login("testenv2");
print_r($result);
} 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();
+ $onelogin->logout();
} elseif (isset($_GET['acs'])) {
if (isset($_SESSION) && isset($_SESSION['AuthNRequestID'])) {
$requestID = $_SESSION['AuthNRequestID'];
@@ -112,3 +92,4 @@
echo 'Login and access to attrs.php page
';
echo 'Show the SP metadata
';
}
+*/
\ No newline at end of file
diff --git a/src/Helpers/IdpHelper.php b/src/Helpers/IdpHelper.php
index 443d093..23176f5 100644
--- a/src/Helpers/IdpHelper.php
+++ b/src/Helpers/IdpHelper.php
@@ -9,6 +9,7 @@ public static function getMetadata($idpName)
if (!file_exists(__DIR__ . "/../Config/idp/" . $idpName . ".xml")) {
throw new \Exception("Invalid IDP Requested", 1);
}
+
$xml = simplexml_load_file(__DIR__ . "/../Config/idp/" . $idpName . '.xml');
$metadata = array();
@@ -16,7 +17,7 @@ public static function getMetadata($idpName)
$metadata['idpSSO'] = $xml->xpath('//SingleSignOnService')[0]->attributes()->Location->__toString();
$metadata['idpSLO'] = $xml->xpath('//SingleLogoutService')[0]->attributes()->Location->__toString();
$metadata['idpCertValue'] = $xml->xpath('//X509Certificate')[0]->__toString();
-
+
return $metadata;
}
}
\ No newline at end of file
diff --git a/src/SpidPHP.php b/src/SpidPHP.php
index 194fae0..ae088ed 100644
--- a/src/SpidPHP.php
+++ b/src/SpidPHP.php
@@ -49,7 +49,7 @@ public function isAuthenticated()
public function login( $idpName, $redirectTo = '', $level = 1 )
{
if (is_null($this->phpSaml)) $this->initStrategy($idpName);
- return $this->phpSaml->login($redirectTo);
+ return $this->phpSaml->login($idpName, $redirectTo);
}
public function logout()
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 8b0ed6f..8d72acc 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -24,7 +24,7 @@ class PhpSamlOneLogin implements PhpSamlInterface
function __construct($idpName = null, $settings)
{
- $this->idpName = $idpName ?? "testenv2";
+ $this->idpName = $idpName ?? "testenv2";
$this->settings = $settings;
$this->init();
}
@@ -49,7 +49,7 @@ private function init()
}
$this->settingsHelper->updateIdpMetadata($this->idpName);
- $this->settings = new Settings($this->settingsHelper->getSettings());
+ $this->oneloginSettings = new Settings($this->settingsHelper->getSettings());
$this->auth = new Auth($this->settingsHelper->getSettings());
}
From 0b0545da9d9c9ac38c2e201c832c30d6497430ec Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 27 Jul 2018 15:14:59 +0200
Subject: [PATCH 27/69] added getAttributes method
---
src/SpidPHP.php | 5 +++++
src/Strategy/Interfaces/PhpSamlInterface.php | 1 +
src/Strategy/PhpSamlOneLogin.php | 5 +++++
3 files changed, 11 insertions(+)
diff --git a/src/SpidPHP.php b/src/SpidPHP.php
index ae088ed..0453db7 100644
--- a/src/SpidPHP.php
+++ b/src/SpidPHP.php
@@ -58,4 +58,9 @@ public function logout()
return $this->phpSaml->logout();
}
+ public function getAttributes()
+ {
+ return $this->phpSaml->getAttributes();
+ }
+
}
\ No newline at end of file
diff --git a/src/Strategy/Interfaces/PhpSamlInterface.php b/src/Strategy/Interfaces/PhpSamlInterface.php
index aaa496d..d21acf3 100644
--- a/src/Strategy/Interfaces/PhpSamlInterface.php
+++ b/src/Strategy/Interfaces/PhpSamlInterface.php
@@ -8,4 +8,5 @@ public function getSupportedIdps();
public function isAuthenticated();
public function login( $idpName, $redirectTo = '', $level = 1 );
public function logout();
+ public function getAttributes();
}
\ No newline at end of file
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 8d72acc..3f2d06a 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -144,4 +144,9 @@ public function logout()
return true;
}
+ public function getAttributes()
+ {
+ return $this->userdata;
+ }
+
}
\ No newline at end of file
From b0f124984004ea15a19d6fb96423c4593890decb Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 27 Jul 2018 15:24:48 +0200
Subject: [PATCH 28/69] WIP: login example
---
example/index.php | 14 +-------------
example/login.php | 28 ++++++++++++++++++++++++++++
example/logout.php | 0
3 files changed, 29 insertions(+), 13 deletions(-)
create mode 100644 example/login.php
create mode 100644 example/logout.php
diff --git a/example/index.php b/example/index.php
index a37ff2c..3f6eb94 100644
--- a/example/index.php
+++ b/example/index.php
@@ -10,21 +10,9 @@
use SpidPHP\SpidPHP;
-echo 'Login
';
-echo 'Login and access to attrs.php page
';
+echo 'Login
';
echo 'Show the SP metadata
';
-$onelogin = new SpidPHP($settings);
-
-if (isset($_GET['sso'])) {
- $result = $onelogin->login("testenv2");
- print_r($result);
- die();
-}
-
-//if (!$onelogin->isAuthenticated()) $onelogin->login();
-
-//if ($onelogin->login()) $onelogin->logout();
/*
diff --git a/example/login.php b/example/login.php
new file mode 100644
index 0000000..3984e2d
--- /dev/null
+++ b/example/login.php
@@ -0,0 +1,28 @@
+isAuthenticated() === false) {
+ $result = $onelogin->login("testenv2");
+ print_r($result);
+ exit();
+}
+
+$attributes = $onelogin->getAttributes();
+
+foreach ($attributes as $key => $attribute) {
+ echo $attribute . "\n";
+}
+
+
diff --git a/example/logout.php b/example/logout.php
new file mode 100644
index 0000000..e69de29
From 5633b9e9874094f096bea903224bb9af8162e1e1 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 27 Jul 2018 16:19:36 +0200
Subject: [PATCH 29/69] cleanup + added login response handler
---
config.yaml.example | 12 --
example/login.php | 2 -
saml-schema-assertion-2.0.xsd | 283 ---------------------------
saml-schema-metadata-SPID-SP.xsd | 139 --------------
src/Strategy/PhpSamlOneLogin.php | 48 ++---
xenc-schema.xsd | 145 --------------
xml.xsd | 287 ----------------------------
xmldsig-core-schema.xsd | 318 -------------------------------
8 files changed, 18 insertions(+), 1216 deletions(-)
delete mode 100644 config.yaml.example
delete mode 100644 saml-schema-assertion-2.0.xsd
delete mode 100644 saml-schema-metadata-SPID-SP.xsd
delete mode 100644 xenc-schema.xsd
delete mode 100644 xml.xsd
delete mode 100644 xmldsig-core-schema.xsd
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/login.php b/example/login.php
index 3984e2d..13f75c6 100644
--- a/example/login.php
+++ b/example/login.php
@@ -11,8 +11,6 @@
$onelogin = new SpidPHP($settings);
-print_r($_POST);
-
if ($onelogin->isAuthenticated() === false) {
$result = $onelogin->login("testenv2");
print_r($result);
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/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 3f2d06a..1a1e309 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -83,7 +83,23 @@ public function getSupportedIdps()
public function isAuthenticated()
{
- if ($this->auth->isAuthenticated) {
+ if (isset($_POST) && isset($_POST['SAMLResponse'])) {
+ $this->auth->processResponse();
+
+ $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();
+
+ }
+ if ($this->auth->isAuthenticated() === false) {
return false;
}
return true;
@@ -98,39 +114,11 @@ public function login( $idpName, $redirectTo = '', $level = 1 )
}
$this->auth->login($redirectTo);
-
- $requestID = null;
- if (isset($_SESSION['AuthNRequestID'])) {
- $requestID = $_SESSION['AuthNRequestID'];
- }
-
- $this->auth->processResponse($requestID);
- unset($_SESSION['AuthNRequestID']);
-
- $errors = $this->auth->getErrors();
- if (!empty($errors)) {
- return $errors;
- }
-
- if (!$this->auth->isAuthenticated()) {
- return false;
- }
- $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();
-
- if (!empty($data['samlUserdata'])) {
- return $data;
- }
-
- return false;
}
public function logout()
{
- if (!$this->auth->isAuthenticated()) {
+ if ($this->auth->isAuthenticated() === false) {
return false;
}
$this->auth->logout();
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 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
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.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
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".
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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.
-
-
-
-
-
-
-
-
-
-
-
-
- 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 @@
-
-
-
-
-
- ]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
From 770f58093ca6a4a3a129810abb6972269181b369 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 27 Jul 2018 16:35:07 +0200
Subject: [PATCH 30/69] added requestid for login validation
---
src/Strategy/PhpSamlOneLogin.php | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 1a1e309..0d62399 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -18,6 +18,7 @@ class PhpSamlOneLogin implements PhpSamlInterface
private $settings = null;
private $auth;
+ private $authRequestID;
private $settingsHelper;
private $oneloginSettings;
private $userdata;
@@ -83,9 +84,9 @@ public function getSupportedIdps()
public function isAuthenticated()
{
- if (isset($_POST) && isset($_POST['SAMLResponse'])) {
- $this->auth->processResponse();
-
+ if (!is_null($this->authRequestID)) {
+ $this->auth->processResponse($this->authRequestID);
+ $this->authRequestID = null;
$errors = $this->auth->getErrors();
if (!empty($errors)) {
@@ -113,7 +114,13 @@ public function login( $idpName, $redirectTo = '', $level = 1 )
return false;
}
- $this->auth->login($redirectTo);
+ $ssoBuiltUrl = $this->auth->login($redirectTo, array(), false, false, true);
+ $this->authRequestID = $this->auth->getLastRequestID();
+
+ header('Pragma: no-cache');
+ header('Cache-Control: no-cache, must-revalidate');
+ header('Location: ' . $ssoBuiltUrl);
+ exit();
}
public function logout()
From 26de813c17c9f0761d3add9f8d9f8a06a981e3e9 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Mon, 30 Jul 2018 08:33:28 +0200
Subject: [PATCH 31/69] exclude and remove .vscode
---
.gitignore | 1 +
.vscode/launch.json | 22 ----------------------
2 files changed, 1 insertion(+), 22 deletions(-)
delete mode 100644 .vscode/launch.json
diff --git a/.gitignore b/.gitignore
index 1dbeb38..5c59cd6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ config.yaml
.directory
AuthnRequest.patched
LogoutRequest.patched
+.vscode
diff --git a/.vscode/launch.json b/.vscode/launch.json
deleted file mode 100644
index 9d9ed65..0000000
--- a/.vscode/launch.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- // Usare IntelliSense per informazioni sui possibili attributi.
- // Al passaggio del mouse vengono visualizzate le descrizioni degli attributi esistenti.
- // Per ulteriori informazioni, visitare: https://go.microsoft.com/fwlink/?linkid=830387
- "version": "0.2.0",
- "configurations": [
- {
- "name": "Listen for XDebug",
- "type": "php",
- "request": "launch",
- "port": 9000
- },
- {
- "name": "Launch currently open script",
- "type": "php",
- "request": "launch",
- "program": "${file}",
- "cwd": "${fileDirname}",
- "port": 9000
- }
- ]
-}
\ No newline at end of file
From 73ae19b49e99df030901c08dcd248034a5ce420b Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Mon, 30 Jul 2018 08:43:52 +0200
Subject: [PATCH 32/69] clean up Makefile
---
Makefile | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/Makefile b/Makefile
index d7728ca..99b49c1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,4 @@
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
AuthnRequest.patched: AuthnRequest.diff
if [ -e $@ ]; then patch -R vendor/onelogin/php-saml/lib/Saml2/AuthnRequest.php $@; fi
@@ -19,4 +14,4 @@ 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
clean:
- rm -rf tmp vendor www/settings.php
+ rm -rf vendor
From 30ce2b9c594b1e3eb1c50fad7ecc0dd730d376d2 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Mon, 30 Jul 2018 08:46:24 +0200
Subject: [PATCH 33/69] exclude and remove .DS_store files
---
.DS_Store | Bin 8196 -> 0 bytes
.gitignore | 2 ++
src/.DS_Store | Bin 6148 -> 0 bytes
src/Config/.DS_Store | Bin 6148 -> 0 bytes
src/Config/idp/.DS_Store | Bin 6148 -> 0 bytes
5 files changed, 2 insertions(+)
delete mode 100644 .DS_Store
delete mode 100644 src/.DS_Store
delete mode 100644 src/Config/.DS_Store
delete mode 100644 src/Config/idp/.DS_Store
diff --git a/.DS_Store b/.DS_Store
deleted file mode 100644
index 207e9eb093e9c48a6ed10101cd775d66007a764f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 8196
zcmeHM&2G~`5S~p+>l9UO0nuKNd_m&Spr)nbfGUMFIaDgBA_xwES|@f}Q^yXr)3k)3
zTzCiI4R{nz9C;8P0KWYp*iKsYfDn}3YIerEGqbzj&aN{q5wS|gE)gvfkpbd-?lP(|
zh4*tBDLK`09h||Q$frl-&@1Yo)RPI>RkUR`ShGy?x6
z0{nh3L7bNrA4o2)4pbrq0G~j!D3Fl{2pd!Jvf=~Dg(-Z>?13p$rcw+h&Czdib?~y{
z1IeX1F=_vgEqf2xtUG5#YJ|Jl#je9@9Z8e~-{|n{0AvkM=gb
zpxN+(2DEX&*f;Q7-$fBFXQ)X5wWy6cLhc{J@+G8z{Iq4xI)|kPyCxlGEWczduZl5!
z%+95KjCVp7X5c|`=vc^YJUMAE`SpyKsk5}%yAkaz+N2Gt(L<_JE$y4`LHm6Il`FJ`
zmF$B!y1%}RoPjKT%J?wo0oHPeS@Ly`tcNXR^a~iLhW)IiI
z8tY%gPSXD*{I@ZeCZAz?l{p?Q<8(QaCuv;~6G`1X{D#y_Yl)pn#=O#MbfdO98J`<%
z&yC{c<*zK4pSUzRWf;@O^vv{&`a#gG$5z~lDpvT6KW$s_K|{%pgTNcgR^y55ba&>i
zZ3KR7xxNz$W7l?|^8Bgm+d;PybbLD!e(JKrFbYOtXKu0ATfMtv-YKp2m&{(Nw7Rln
zuC0~&{erP@v$Vds+d6sOd((gW0pOr8^)97Z`8=#YLQ=~+s)xQ8`1@QPG)YGQ(8tCF
z6s7?Zp_l|HrF&6fN-Z)2)+|m52djywPM)l>(amoUW+ZNpDOk(Rl}KgZa7>r&o^k)VYOj6hzlZIS2ywbQ@gr!Z
F;0G5C;=BL=
diff --git a/.gitignore b/.gitignore
index 5c59cd6..50b1cd9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,5 @@ config.yaml
AuthnRequest.patched
LogoutRequest.patched
.vscode
+.DS_Store
+
diff --git a/src/.DS_Store b/src/.DS_Store
deleted file mode 100644
index a500411ee3c77ad6f80303e03aa780d1f91ce863..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 6148
zcmeHK!EVz)5S>j!x=Dq|0jWLug2W+0HKF2wDp_eO(OV@WH~?yGViHTPH;Nsi5>olX
zN5CKODSQE+18;Vhs!rh03qr6X&A!?3ytVhO<@FMg7|ez~QJ07$oUzeH^9$qa>}%Gr
znHEs!F;W^GXX;Iysd%m0CH_VQc$gvLCLEZX+Bi*ftuyRLXQ)g3sSaa`?R~WSo9zFyhnb2+4B~@-+$Qi_V)bc
zvMsmo`TNIb=NIo6AC{M&^fXA|h1GV);!pUDpf<^O;WW=wK0=;3oAi_t%4mXiO2xI;
zo#pxhzb@AnozNJyAw_f!)&s=o*IDA@3QMBC#OM*)ghq6+Qop@YkFGPPfK$LJa1#aW
zCs1zPgyd?S0#1SdLIM6hcyPwRVr5W&I?(7N0I-R)HpKiN#2n9JV6ifYD==ZGKtmPw
zh#?FedC%4b7Au2>PQo5OguSz{ClsOYj`2NRP9iYqTBm?hpsv7%>2`VlKl=UozfN*J
zr+`!7pHe_H55vO&reyclwaM{b>%q_9Y+P3vyrLk`TQO>RE8c-?L*C;67+9J%rYLs$C0eK|*&5UQf>*tldLqwuC%|fC!5lJ-0S`*zJ!sFalq~<&g
zpx`<5=d{o%ES}EGzrX?cX*=Ui>y<7UH7P*<|E)`DZ#R@=3Y5`AgL5
zjeGYWNZFFDN3BosP|xBrDW{WOGCpK$KPiW)(?4ik+~`SqkoRZD?I$~0l}WDpW0Ra`
zeS{o+%vGjmJv~*~#LN@h0V$iZdEDNZ&%19r!RxTQ=mhgH?7r#*TU+5`(Ui}ghi~^z
zPS3y2zb(H1usb2}ks5jI@ER_lxaFP2V^wH1fQO@>(tA?Wr-C#MK$D`F5;}#w1COFF
z@D1oCjcB++;3e{J6A06bXTUSy8CVYn+;J!$uE*>6x9|*j2G)oHJ|6-!#>io1(HtG<
zObGzw-$*0S&CfqDUItlY+%;TOcT!kWB
z=^+9WP9n1Cd(VJpV3~osHQRjuzx#9jzntVP&wyv(zhXc%cH`Y1mgMf%mBsO08=#$_
qv2a{v@g@a|xr!0XSMdg#5%>dEfRV$>B0LcPBVcIoooC>$GH?Z3B5R)j
diff --git a/src/Config/idp/.DS_Store b/src/Config/idp/.DS_Store
deleted file mode 100644
index 505157fb3008733e968f85caab1c60219c19f558..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 6148
zcmeHKyH3ME5S)b+k)TLPc_kGRe8DLS1vNi_0(6EH1VrhIf8j6qGnjn{6d4*M8Z;~I
z&fR*)XHVhv0#lzJ6y8FcTDq}=C?{SNJJmCx{c%D>$pK$IWwq!m;
z{NmqXxEMCq>tVBIjX&Tk{rEkME149K0#ZNX}$M^Th@&DXr%3&+HuGaq!Keg<3@nH2bI1wH^OHXL>U
From 3a5be353965a1c6601b78be4b1e7cd99d8448b2b Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Mon, 30 Jul 2018 09:14:52 +0200
Subject: [PATCH 34/69] unify src/config to src/Config
---
src/{config => Config}/OneloginSamlConfig.php | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename src/{config => Config}/OneloginSamlConfig.php (100%)
diff --git a/src/config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
similarity index 100%
rename from src/config/OneloginSamlConfig.php
rename to src/Config/OneloginSamlConfig.php
From f66963a1a204edb72de7b99feeb797c3676607bd Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Mon, 30 Jul 2018 09:15:17 +0200
Subject: [PATCH 35/69] use paths for php-saml v 3.x
---
Makefile | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
index 99b49c1..2ae1a17 100644
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,13 @@
all: sp.key AuthnRequest.patched LogoutRequest.patched
AuthnRequest.patched: AuthnRequest.diff
- if [ -e $@ ]; then patch -R vendor/onelogin/php-saml/lib/Saml2/AuthnRequest.php $@; fi
- patch -N vendor/onelogin/php-saml/lib/Saml2/AuthnRequest.php $<
+ 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: LogoutRequest.diff
- if [ -e $@ ]; then patch -R vendor/onelogin/php-saml/lib/Saml2/LogoutRequest.php $@; fi
- patch -N vendor/onelogin/php-saml/lib/Saml2/LogoutRequest.php $<
+ 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:
From cdf607af93bfe4ef301775f9dcd1b493676cc590 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Mon, 30 Jul 2018 10:11:50 +0200
Subject: [PATCH 36/69] add links to index, and assertion consuming service
page
---
example/acs.php | 25 +++++++++++++++
example/index.php | 81 ++---------------------------------------------
2 files changed, 27 insertions(+), 79 deletions(-)
create mode 100644 example/acs.php
diff --git a/example/acs.php b/example/acs.php
new file mode 100644
index 0000000..93d8e8c
--- /dev/null
+++ b/example/acs.php
@@ -0,0 +1,25 @@
+isAuthenticated()) {
+ $attributes = $onelogin->getAttributes();
+ echo "logged in !" . PHP_EOL;
+ var_dump($attributes);
+ foreach ($attributes as $key => $attribute) {
+ echo $attribute . "\n";
+ }
+} else {
+ echo "not logged in !" . PHP_EOL;
+}
+
+echo 'Login
';
diff --git a/example/index.php b/example/index.php
index 3f6eb94..f9a3c71 100644
--- a/example/index.php
+++ b/example/index.php
@@ -1,83 +1,6 @@
Login
';
echo 'Show the SP metadata
';
-
-
-
-/*
-if (isset($_GET['sso'])) {
- $result = $onelogin->login("testenv2");
- print_r($result);
-} elseif (isset($_GET['slo'])) {
- $onelogin->logout();
-} 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 'Name | Values | ';
- foreach ($attributes as $attributeName => $attributeValues) {
- echo '' . htmlentities($attributeName) . ' | ';
- foreach ($attributeValues as $attributeValue) {
- echo '- ' . htmlentities($attributeValue) . '
';
- }
- echo ' |
';
- }
- 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
';
-}
-*/
\ No newline at end of file
+echo 'Logout
';
+echo 'Assertion Consuming Service
';
From 7d86a9d75b97eb3023e8ec1fa7392d47f7affcbb Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Mon, 30 Jul 2018 10:17:36 +0200
Subject: [PATCH 37/69] implement logout
---
example/logout.php | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/example/logout.php b/example/logout.php
index e69de29..1d474cd 100644
--- a/example/logout.php
+++ b/example/logout.php
@@ -0,0 +1,18 @@
+isAuthenticated()) {
+ $result = $onelogin->logout();
+ print_r($result);
+ exit();
+}
From a4849c31aabbfc83bf31b03115233962c2713537 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Mon, 30 Jul 2018 10:18:03 +0200
Subject: [PATCH 38/69] configure acs and slo
---
example/settings.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/example/settings.php b/example/settings.php
index 4a0cd20..378dbd0 100644
--- a/example/settings.php
+++ b/example/settings.php
@@ -6,6 +6,6 @@
'spEntityId' => $base."/metadata.php",
'spKeyFile' => __DIR__ . "/../sp.key",
'spCrtFile' => __DIR__ . "/../sp.crt",
- 'spAcsUrl' => $base."/index.php?acs",
- 'spSloUrl' => $base."/index.php?slo"
+ 'spAcsUrl' => $base."/acs.php",
+ 'spSloUrl' => $base."/logout.php"
];
From 8af2459a2ae0a3ffbbc7cb1413afc0bfce7627ae Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Mon, 30 Jul 2018 22:33:42 +0200
Subject: [PATCH 39/69] fix login status
---
src/Strategy/PhpSamlOneLogin.php | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 0d62399..cb4111a 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -84,6 +84,7 @@ public function getSupportedIdps()
public function isAuthenticated()
{
+ if (isset($_SESSION) && isset($_SESSION['authReqID'])) $this->authRequestID =$_SESSION['authReqID'];
if (!is_null($this->authRequestID)) {
$this->auth->processResponse($this->authRequestID);
$this->authRequestID = null;
@@ -115,7 +116,11 @@ public function login( $idpName, $redirectTo = '', $level = 1 )
}
$ssoBuiltUrl = $this->auth->login($redirectTo, array(), false, false, true);
+ if (session_status() == PHP_SESSION_NONE) {
+ session_start();
+ }
$this->authRequestID = $this->auth->getLastRequestID();
+ $_SESSION['authReqID'] = $this->auth->getLastRequestID();
header('Pragma: no-cache');
header('Cache-Control: no-cache, must-revalidate');
From 138be5bb8ea918e40d3f438152096e0349983a71 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Mon, 30 Jul 2018 23:27:39 +0200
Subject: [PATCH 40/69] testing session test saving request id to session
---
src/Strategy/PhpSamlOneLogin.php | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index cb4111a..29775b7 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -84,7 +84,10 @@ public function getSupportedIdps()
public function isAuthenticated()
{
- if (isset($_SESSION) && isset($_SESSION['authReqID'])) $this->authRequestID =$_SESSION['authReqID'];
+ if (isset($_SESSION) && isset($_SESSION['authReqID'])) {
+ $this->rebuildPhpSamlOnelogin($_SESSION['idpName']);
+ $this->authRequestID =$_SESSION['authReqID'];
+ }
if (!is_null($this->authRequestID)) {
$this->auth->processResponse($this->authRequestID);
$this->authRequestID = null;
@@ -116,11 +119,10 @@ public function login( $idpName, $redirectTo = '', $level = 1 )
}
$ssoBuiltUrl = $this->auth->login($redirectTo, array(), false, false, true);
- if (session_status() == PHP_SESSION_NONE) {
- session_start();
- }
+
$this->authRequestID = $this->auth->getLastRequestID();
$_SESSION['authReqID'] = $this->auth->getLastRequestID();
+ $_SESSION['idpName'] = $idpName;
header('Pragma: no-cache');
header('Cache-Control: no-cache, must-revalidate');
From 1426c795fac3ba4a2391bcf8ebfbd1e58c4ac432 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Mon, 30 Jul 2018 23:50:17 +0200
Subject: [PATCH 41/69] WIP saving request id to session
---
src/SpidPHP.php | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/SpidPHP.php b/src/SpidPHP.php
index 0453db7..0c7c2e9 100644
--- a/src/SpidPHP.php
+++ b/src/SpidPHP.php
@@ -12,7 +12,8 @@ class SpidPHP implements PhpSamlInterface
private $settings = null;
public function __construct($settings = null, $mode = 'onelogin')
- {
+ {
+ session_start();
$this->mode = $mode;
$this->settings = $settings;
}
@@ -42,6 +43,7 @@ public function getSupportedIdps()
public function isAuthenticated()
{
+ if (isset($_SESSION['idpName']) && is_null($this->phpSaml)) $this->initStrategy($_SESSION['idpName']);
if (is_null($this->phpSaml)) return false;
return $this->phpSaml->isAuthenticated();
}
From 3ded4aa26ddd332485573777c2ce28e0afea4898 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Tue, 31 Jul 2018 22:28:40 +0200
Subject: [PATCH 42/69] fix esempio login funzionante
---
example/acs.php | 7 +++++--
example/login.php | 11 +----------
example/settings.php | 2 +-
src/Strategy/PhpSamlOneLogin.php | 3 ++-
4 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/example/acs.php b/example/acs.php
index 93d8e8c..c8bf76a 100644
--- a/example/acs.php
+++ b/example/acs.php
@@ -16,10 +16,13 @@
echo "logged in !" . PHP_EOL;
var_dump($attributes);
foreach ($attributes as $key => $attribute) {
- echo $attribute . "\n";
+ echo $key .": " . $attribute . "\n";
}
+
+ echo 'Login
';
} else {
echo "not logged in !" . PHP_EOL;
+ echo 'Login
';
}
-echo 'Login
';
+
diff --git a/example/login.php b/example/login.php
index 13f75c6..a9607f2 100644
--- a/example/login.php
+++ b/example/login.php
@@ -12,15 +12,6 @@
$onelogin = new SpidPHP($settings);
if ($onelogin->isAuthenticated() === false) {
- $result = $onelogin->login("testenv2");
- print_r($result);
- exit();
+ $onelogin->login("testenv2");
}
-
-$attributes = $onelogin->getAttributes();
-
-foreach ($attributes as $key => $attribute) {
- echo $attribute . "\n";
-}
-
diff --git a/example/settings.php b/example/settings.php
index 378dbd0..054c3a3 100644
--- a/example/settings.php
+++ b/example/settings.php
@@ -1,6 +1,6 @@
$base,
'spEntityId' => $base."/metadata.php",
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 29775b7..38419c8 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -88,7 +88,7 @@ public function isAuthenticated()
$this->rebuildPhpSamlOnelogin($_SESSION['idpName']);
$this->authRequestID =$_SESSION['authReqID'];
}
- if (!is_null($this->authRequestID)) {
+ if (!is_null($this->authRequestID) && isset($_POST['SAMLResponse'])) {
$this->auth->processResponse($this->authRequestID);
$this->authRequestID = null;
$errors = $this->auth->getErrors();
@@ -102,6 +102,7 @@ public function isAuthenticated()
$this->userdata['samlNameId'] = $this->auth->getNameId();
$this->userdata['samlNameIdFormat'] = $this->auth->getNameIdFormat();
$this->userdata['samlSessionIndex'] = $this->auth->getSessionIndex();
+ $_SESSION['userdata'] = $this->userdata;
}
if ($this->auth->isAuthenticated() === false) {
From e8ef3357d3e1ffaf704da4d39b24a9f271498076 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Tue, 31 Jul 2018 22:55:02 +0200
Subject: [PATCH 43/69] moved logout function to check auth
---
example/logout.php | 4 +---
src/SpidPHP.php | 4 +++-
src/Strategy/PhpSamlOneLogin.php | 25 ++++++++++++++++++-------
3 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/example/logout.php b/example/logout.php
index 1d474cd..e618fe2 100644
--- a/example/logout.php
+++ b/example/logout.php
@@ -12,7 +12,5 @@
$onelogin = new SpidPHP($settings);
if ($onelogin->isAuthenticated()) {
- $result = $onelogin->logout();
- print_r($result);
- exit();
+ $onelogin->logout();
}
diff --git a/src/SpidPHP.php b/src/SpidPHP.php
index 0c7c2e9..7f99141 100644
--- a/src/SpidPHP.php
+++ b/src/SpidPHP.php
@@ -56,12 +56,14 @@ public function login( $idpName, $redirectTo = '', $level = 1 )
public function logout()
{
+ if (isset($_SESSION['idpName']) && is_null($this->phpSaml)) $this->initStrategy($_SESSION['idpName']);
if (is_null($this->phpSaml)) return false;
return $this->phpSaml->logout();
}
public function getAttributes()
- {
+ {
+ if (is_null($this->phpSaml)) return false;
return $this->phpSaml->getAttributes();
}
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 38419c8..1a7599e 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -88,6 +88,17 @@ public function isAuthenticated()
$this->rebuildPhpSamlOnelogin($_SESSION['idpName']);
$this->authRequestID =$_SESSION['authReqID'];
}
+
+ if (isset($_SESSION) && isset($_SESSION['LogoutRequestID'])) {
+ $this->auth->processSLO(false, $_SESSION['LogoutRequestID']);
+
+ $errors = $this->auth->getErrors();
+ if (!empty($errors)) {
+ return $errors;
+ }
+ return false;
+ }
+
if (!is_null($this->authRequestID) && isset($_POST['SAMLResponse'])) {
$this->auth->processResponse($this->authRequestID);
$this->authRequestID = null;
@@ -137,14 +148,14 @@ public function logout()
return false;
}
$this->auth->logout();
- $this->auth->processSLO();
- $errors = $this->auth->getErrors();
- if (!empty($errors)) {
- return $errors;
- }
-
- return true;
+ $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()
From ee7a556985e1fa33a9ec4aaac1f62b6b5b62173a Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 2 Aug 2018 14:18:00 +0200
Subject: [PATCH 44/69] better example and check authentication status
---
example/acs.php | 3 +--
example/login.php | 2 ++
example/logout.php | 2 ++
example/metadata.php | 3 ---
src/Strategy/PhpSamlOneLogin.php | 15 ++++++++-------
5 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/example/acs.php b/example/acs.php
index c8bf76a..25cf118 100644
--- a/example/acs.php
+++ b/example/acs.php
@@ -14,12 +14,11 @@
if ($onelogin->isAuthenticated()) {
$attributes = $onelogin->getAttributes();
echo "logged in !" . PHP_EOL;
- var_dump($attributes);
foreach ($attributes as $key => $attribute) {
echo $key .": " . $attribute . "\n";
}
- echo 'Login
';
+ echo 'Logout
';
} else {
echo "not logged in !" . PHP_EOL;
echo 'Login
';
diff --git a/example/login.php b/example/login.php
index a9607f2..3f24a21 100644
--- a/example/login.php
+++ b/example/login.php
@@ -13,5 +13,7 @@
if ($onelogin->isAuthenticated() === false) {
$onelogin->login("testenv2");
+} else {
+ echo "Already logged in!";
}
diff --git a/example/logout.php b/example/logout.php
index e618fe2..6f56ac5 100644
--- a/example/logout.php
+++ b/example/logout.php
@@ -13,4 +13,6 @@
if ($onelogin->isAuthenticated()) {
$onelogin->logout();
+} else {
+ echo "Logged out!";
}
diff --git a/example/metadata.php b/example/metadata.php
index 374fc15..3358573 100644
--- a/example/metadata.php
+++ b/example/metadata.php
@@ -15,6 +15,3 @@
header('Content-Type: text/xml');
echo $metadata;
-//if (!$onelogin->isAuthenticated()) $onelogin->login();
-
-//if ($onelogin->login()) $onelogin->logout();
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 1a7599e..8d16f56 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -54,7 +54,7 @@ private function init()
$this->auth = new Auth($this->settingsHelper->getSettings());
}
- private function rebuildPhpSamlOnelogin($idpName)
+ private function changeIdp($idpName)
{
if ($this->idpName != $idpName) {
$this->idpName = $idpName;
@@ -84,13 +84,14 @@ public function getSupportedIdps()
public function isAuthenticated()
{
- if (isset($_SESSION) && isset($_SESSION['authReqID'])) {
- $this->rebuildPhpSamlOnelogin($_SESSION['idpName']);
- $this->authRequestID =$_SESSION['authReqID'];
+ if (isset($_SESSION) && isset($_SESSION['idpName'])) {
+ $this->changeIdp($_SESSION['idpName']);
+ $this->authRequestID = $_SESSION['authReqID'];
}
if (isset($_SESSION) && isset($_SESSION['LogoutRequestID'])) {
$this->auth->processSLO(false, $_SESSION['LogoutRequestID']);
+ unset($_SESSION['LogoutRequestID']);
$errors = $this->auth->getErrors();
if (!empty($errors)) {
@@ -99,9 +100,9 @@ public function isAuthenticated()
return false;
}
- if (!is_null($this->authRequestID) && isset($_POST['SAMLResponse'])) {
- $this->auth->processResponse($this->authRequestID);
- $this->authRequestID = null;
+ if (isset($_SESSION['authReqID']) && isset($_POST['SAMLResponse'])) {
+ $this->auth->processResponse($_SESSION['authReqID']);
+ unset($_SESSION['authReqID']);
$errors = $this->auth->getErrors();
if (!empty($errors)) {
From 9aa48ba338332f0fa179ea4138a1827f01841872 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 2 Aug 2018 14:20:39 +0200
Subject: [PATCH 45/69] bugfix method name
---
src/Strategy/PhpSamlOneLogin.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 8d16f56..63f7e3f 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -125,7 +125,7 @@ public function isAuthenticated()
public function login( $idpName, $redirectTo = '', $level = 1 )
{
- $this->rebuildPhpSamlOnelogin($idpName);
+ $this->changeIdp()($idpName);
if ($this->auth->isAuthenticated()) {
return false;
From 095c9e99e1dd6d16500a1e4f255f1e576b4e7251 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 2 Aug 2018 14:22:38 +0200
Subject: [PATCH 46/69] bugfix
---
src/Strategy/PhpSamlOneLogin.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 63f7e3f..48cac81 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -125,7 +125,7 @@ public function isAuthenticated()
public function login( $idpName, $redirectTo = '', $level = 1 )
{
- $this->changeIdp()($idpName);
+ $this->changeIdp($idpName);
if ($this->auth->isAuthenticated()) {
return false;
From 2aded590b445da0052e54363aed41f3e42c485c2 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 2 Aug 2018 14:43:23 +0200
Subject: [PATCH 47/69] test requesting attributes
---
src/Config/OneloginSamlConfig.php | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
index dfc452f..4018209 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneloginSamlConfig.php
@@ -67,6 +67,24 @@ public function getSettings()
),
'x509cert' => $this->idpCertValue,
),
+ "attributeConsumingService"=> array(
+ "serviceName" => "SP test",
+ "serviceDescription" => "Test Service",
+ "requestedAttributes" => array(
+ array(
+ "name" => "name",
+ "isRequired" => false,
+ ),
+ array(
+ "familyName" => "name",
+ "isRequired" => false,
+ ),
+ array(
+ "name" => "fiscalNumber",
+ "isRequired" => false,
+ ),
+ )
+ ),
'security' => array(
'authnRequestsSigned' => true,
'logoutRequestSigned' => true,
From fb6aaca51be07db77bf78e5e774d8a72a013b975 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 2 Aug 2018 15:12:21 +0200
Subject: [PATCH 48/69] testing settings - request attributes
---
src/Config/OneloginSamlConfig.php | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
index 4018209..adebd22 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneloginSamlConfig.php
@@ -71,17 +71,23 @@ public function getSettings()
"serviceName" => "SP test",
"serviceDescription" => "Test Service",
"requestedAttributes" => array(
- array(
- "name" => "name",
- "isRequired" => false,
+ array (
+ 'nameFormat' => OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
+ 'isRequired' => true,
+ 'name' => 'name',
+ 'friendlyName' => 'Nome'
),
- array(
- "familyName" => "name",
- "isRequired" => false,
+ array (
+ 'nameFormat' => OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
+ 'isRequired' => true,
+ 'name' => 'familyName',
+ 'friendlyName' => 'Cognome'
),
- array(
- "name" => "fiscalNumber",
- "isRequired" => false,
+ array (
+ 'nameFormat' => OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
+ 'isRequired' => true,
+ 'name' => 'fiscalNumber',
+ 'friendlyName' => 'Codice Fiscale'
),
)
),
From 155e2bef39d0d1ef8da6183835ab490beef98eb0 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Thu, 2 Aug 2018 15:13:21 +0200
Subject: [PATCH 49/69] fixed namespace
---
src/Config/OneloginSamlConfig.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
index adebd22..61c76e8 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneloginSamlConfig.php
@@ -72,19 +72,19 @@ public function getSettings()
"serviceDescription" => "Test Service",
"requestedAttributes" => array(
array (
- 'nameFormat' => OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
+ 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
'isRequired' => true,
'name' => 'name',
'friendlyName' => 'Nome'
),
array (
- 'nameFormat' => OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
+ 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
'isRequired' => true,
'name' => 'familyName',
'friendlyName' => 'Cognome'
),
array (
- 'nameFormat' => OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
+ 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
'isRequired' => true,
'name' => 'fiscalNumber',
'friendlyName' => 'Codice Fiscale'
From 6750bc7dcc613b76a3ba21e32f1b62cf1b114871 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Thu, 2 Aug 2018 15:38:23 +0200
Subject: [PATCH 50/69] move the attrCS key under sp
---
src/Config/OneloginSamlConfig.php | 50 +++++++++++++++----------------
1 file changed, 25 insertions(+), 25 deletions(-)
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
index 61c76e8..bca06c8 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneloginSamlConfig.php
@@ -56,6 +56,30 @@ public function getSettings()
'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_URI,
+ 'isRequired' => true,
+ 'name' => 'name',
+ 'friendlyName' => 'Nome'
+ ),
+ array (
+ 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
+ 'isRequired' => true,
+ 'name' => 'familyName',
+ 'friendlyName' => 'Cognome'
+ ),
+ array (
+ 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
+ 'isRequired' => true,
+ 'name' => 'fiscalNumber',
+ 'friendlyName' => 'Codice Fiscale'
+ ),
+ )
+ ),
),
'idp' => array(
'entityId' => $this->idpEntityId,
@@ -67,30 +91,6 @@ public function getSettings()
),
'x509cert' => $this->idpCertValue,
),
- "attributeConsumingService"=> array(
- "serviceName" => "SP test",
- "serviceDescription" => "Test Service",
- "requestedAttributes" => array(
- array (
- 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
- 'isRequired' => true,
- 'name' => 'name',
- 'friendlyName' => 'Nome'
- ),
- array (
- 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
- 'isRequired' => true,
- 'name' => 'familyName',
- 'friendlyName' => 'Cognome'
- ),
- array (
- 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
- 'isRequired' => true,
- 'name' => 'fiscalNumber',
- 'friendlyName' => 'Codice Fiscale'
- ),
- )
- ),
'security' => array(
'authnRequestsSigned' => true,
'logoutRequestSigned' => true,
@@ -142,4 +142,4 @@ public function updateSpData($sp) {
return $this->getSettings();
}
-}
\ No newline at end of file
+}
From f8120da447d9a55ce2ac30d1448df73ecf7ecc4b Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Fri, 3 Aug 2018 10:51:49 +0200
Subject: [PATCH 51/69] cleanup patched files
---
Makefile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Makefile b/Makefile
index cca4cc9..ee5440e 100644
--- a/Makefile
+++ b/Makefile
@@ -17,3 +17,5 @@ sp.key:
clean:
rm -rf vendor
+ rm -f AuthnRequest.patched
+ rm -f LogoutRequest.patched
From 9ef1595495573475648e01e2c9128ae8270e0202 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Fri, 3 Aug 2018 10:52:11 +0200
Subject: [PATCH 52/69] composer update
---
composer.lock | 262 +++-----------------------------------------------
1 file changed, 11 insertions(+), 251 deletions(-)
diff --git a/composer.lock b/composer.lock
index bedc328..b2aabb3 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1,10 +1,10 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "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": "9c614b6245789a0e2cf885b1e6fc7014",
"packages": [
{
"name": "onelogin/php-saml",
@@ -12,12 +12,12 @@
"source": {
"type": "git",
"url": "https://github.com/onelogin/php-saml.git",
- "reference": "03efada0d2485268576a810834f2d61f9ff659aa"
+ "reference": "e0c5827d7ccff72b6cf19f55420cad0e4eea5faf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/onelogin/php-saml/zipball/03efada0d2485268576a810834f2d61f9ff659aa",
- "reference": "03efada0d2485268576a810834f2d61f9ff659aa",
+ "url": "https://api.github.com/repos/onelogin/php-saml/zipball/e0c5827d7ccff72b6cf19f55420cad0e4eea5faf",
+ "reference": "e0c5827d7ccff72b6cf19f55420cad0e4eea5faf",
"shasum": ""
},
"require": {
@@ -54,7 +54,7 @@
"onelogin",
"saml"
],
- "time": "2018-07-08T16:01:32+00:00"
+ "time": "2018-08-02T15:43:25+00:00"
},
{
"name": "robrichards/xmlseclibs",
@@ -98,16 +98,16 @@
},
{
"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,247 +145,7 @@
"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.2",
- "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.5.0",
- "source": {
- "type": "git",
- "url": "https://github.com/twigphp/Twig.git",
- "reference": "6a5f676b77a90823c2d4eaf76137b771adf31323"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/6a5f676b77a90823c2d4eaf76137b771adf31323",
- "reference": "6a5f676b77a90823c2d4eaf76137b771adf31323",
- "shasum": ""
- },
- "require": {
- "php": "^7.0",
- "symfony/polyfill-ctype": "^1.8",
- "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.5-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": "https://twig.symfony.com/contributors",
- "role": "Contributors"
- }
- ],
- "description": "Twig, the flexible, fast, and secure template language for PHP",
- "homepage": "https://twig.symfony.com",
- "keywords": [
- "templating"
- ],
- "time": "2018-07-13T07:18:09+00:00"
+ "time": "2018-07-26T23:47:18+00:00"
}
],
"packages-dev": [],
From a836d92a301d8999046974a6070833d49581a009 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Fri, 3 Aug 2018 10:55:44 +0200
Subject: [PATCH 53/69] refresh patches; patc php-saml to send optional
attribute AttributeConsumingServiceIndex (required for #21) and
AssertionConsumerServiceIndex instead of AssertionConsumerServiceURL +
ProtocolBinding
---
AuthnRequest.diff | 8 ++++++--
LogoutRequest.diff | 2 +-
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/AuthnRequest.diff b/AuthnRequest.diff
index e11c2e7..e3265b4 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}
---
+> AssertionConsumerServiceIndex="1"
+> AttributeConsumingServiceIndex="1">
> {$spEntityId}
diff --git a/LogoutRequest.diff b/LogoutRequest.diff
index 19a77dc..782267d 100644
--- a/LogoutRequest.diff
+++ b/LogoutRequest.diff
@@ -1,4 +1,4 @@
-107c107
+128c128
< {$spEntityId}
---
> {$spEntityId}
From 2c7a36eb1eb3f5d14b0d2808875db99682384a4a Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 3 Aug 2018 13:03:56 +0200
Subject: [PATCH 54/69] aggiunta cartella idp e lista idp supportati
---
.gitignore | 3 +++
example/acs.php | 2 +-
example/idps.php | 11 +++++++++
idp_metadata/put_idp_metadata_here | 0
src/Config/OneloginSamlConfig.php | 16 ++++++++----
src/Config/idp/testenv2.xml | 39 ------------------------------
src/Helpers/IdpHelper.php | 4 +--
src/SpidPHP.php | 3 ++-
src/Strategy/PhpSamlOneLogin.php | 21 ++++++++++++----
9 files changed, 46 insertions(+), 53 deletions(-)
create mode 100644 example/idps.php
create mode 100644 idp_metadata/put_idp_metadata_here
delete mode 100644 src/Config/idp/testenv2.xml
diff --git a/.gitignore b/.gitignore
index 50b1cd9..1d93f62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,6 @@ LogoutRequest.patched
.vscode
.DS_Store
+src/Config/idp/*.xml
+
+idp_metadata/*.xml
\ No newline at end of file
diff --git a/example/acs.php b/example/acs.php
index 25cf118..e83c9c3 100644
--- a/example/acs.php
+++ b/example/acs.php
@@ -15,7 +15,7 @@
$attributes = $onelogin->getAttributes();
echo "logged in !" . PHP_EOL;
foreach ($attributes as $key => $attribute) {
- echo $key .": " . $attribute . "\n";
+ echo $key .": " . $attribute . "
";
}
echo 'Logout
';
diff --git a/example/idps.php b/example/idps.php
new file mode 100644
index 0000000..1406f0f
--- /dev/null
+++ b/example/idps.php
@@ -0,0 +1,11 @@
+getSupportedIdps() as $key => $idp) {
+ echo $key . ' - ' . $idp . '
';
+}
\ No newline at end of file
diff --git a/idp_metadata/put_idp_metadata_here b/idp_metadata/put_idp_metadata_here
new file mode 100644
index 0000000..e69de29
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
index bca06c8..8c9fabd 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneloginSamlConfig.php
@@ -22,6 +22,10 @@ class OneloginSamlConfig
var $idpSSO = null;
var $idpSLO = null;
var $idpCertValue = null;
+
+ var $level = 1;
+
+ var $idp_list = array();
private $is_not_updatable = ['spKeyFileValue', 'spCrtFileValue', 'idpEntityId', 'idpSSO', 'idpSLO', 'idpCertValue'];
@@ -61,19 +65,19 @@ public function getSettings()
"serviceDescription" => "Test Service",
"requestedAttributes" => array(
array (
- 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
+ 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_BASIC,
'isRequired' => true,
'name' => 'name',
'friendlyName' => 'Nome'
),
array (
- 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
+ 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_BASIC,
'isRequired' => true,
'name' => 'familyName',
'friendlyName' => 'Cognome'
),
array (
- 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_URI,
+ 'nameFormat' => \OneLogin\Saml2\Constants::ATTRNAME_FORMAT_BASIC,
'isRequired' => true,
'name' => 'fiscalNumber',
'friendlyName' => 'Codice Fiscale'
@@ -97,14 +101,13 @@ public function getSettings()
'logoutResponseSigned' => true,
'signMetadata' => true,
'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
- 'requestedAuthnContext' => array('https://www.spid.gov.it/SpidL1'),
+ 'requestedAuthnContext' => array('https://www.spid.gov.it/SpidL' . $this->level),
),
);
}
public function updateSettings($settings) {
foreach ($settings as $key => $value) {
- // do not update idp os sp cert file values, they are updated in their own method
if (!property_exists(OneloginSamlConfig::class, $key)) {
continue;
}
@@ -124,6 +127,9 @@ public function updateSettings($settings) {
}
public function updateIdpMetadata($idpName) {
+ if (!array_key_exists($idpName, $this->idp_list)) {
+ throw new Exception("Unsupported IDP provided", 1);
+ }
$metadata = IdpHelper::getMetadata($idpName);
foreach ($metadata as $key => $value) {
if (property_exists(OneloginSamlConfig::class, $key) && strpos($key, "idp") !== false) {
diff --git a/src/Config/idp/testenv2.xml b/src/Config/idp/testenv2.xml
deleted file mode 100644
index 1030cb0..0000000
--- a/src/Config/idp/testenv2.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
- MIIDiDCCAnCgAwIBAgIJAJnqANY7GvtNMA0GCSqGSIb3DQEBCwUAMFkxCzAJBgNV
- BAYTAklUMQ4wDAYDVQQIDAVJdGFseTENMAsGA1UEBwwEUm9tZTERMA8GA1UECgwI
- dGVzdGVudjIxGDAWBgNVBAMMDyR7YW5zaWJsZV9mcWRufTAeFw0xODA3MTkxMzEw
- MDVaFw0xOTA3MTkxMzEwMDVaMFkxCzAJBgNVBAYTAklUMQ4wDAYDVQQIDAVJdGFs
- eTENMAsGA1UEBwwEUm9tZTERMA8GA1UECgwIdGVzdGVudjIxGDAWBgNVBAMMDyR7
- YW5zaWJsZV9mcWRufTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALTP
- ycItk7xvubL0WgegvbtCvhzeCq13WorzjYQdpWvUwY8YmL51h6ssKfWMfnSj96Ix
- lJw2HTm+TgHK2/S7Iw7gh6xoaY+LDmkZGJKzUSFR/Hn7WbFNb3jytowiNDQdcBZd
- hNhEnDvd2fLMGxD81qdlMx3y5XHP+p9Gc8bjp8aShGw+DQpWBXcfoDnCXz5ywmnR
- oD66CnMFMQXmD0wZf79/0fY+Muwn83r7P0h6bJCFDjPdGiSeo7q5AJKkERoNoedc
- HThCuT0uN36bDaVBIcSxVtPjvVhfcNIVN5JHaCLZT89aU8DAJlTUiO3u5Nj4aDjD
- XAhxMWkwGbHXCznhjVMCAwEAAaNTMFEwHQYDVR0OBBYEFH1/ReU+04oYtVpMgD/z
- VCPuagu6MB8GA1UdIwQYMBaAFH1/ReU+04oYtVpMgD/zVCPuagu6MA8GA1UdEwEB
- /wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAWT9+r+ojVmxUUZvq8/TumEX9Y0
- FxxQebTcPMeumA58mp9kDCeNK73PZ6cbQSGXzwbNmHw48N2kZMl3rS8ddYPG3nFx
- EZO5Xi0De2SLGwLZX43lfD4BHhhqhTlnBK8cL+LvySQ32X1vL8aKly/UTez3/DCr
- dTqFjp1V0PdY2q0Ni3UAiO90MpFGbP+aAQ1LGtI0EWpDCVAqqgAA2EA+s0AlwbC5
- cuDbQUjHA5dhkWT/4kvHB/E5zPZUtRV4d3mYBs33lfIyKXWjjgR4T8j01wMk2LWC
- nBU8i4mCb1w3v94KcRbnK23bJLz+zNp6I3belhLknSahyjKPl+6FBSyW/GE=
-
-
-
-
-
-
-
- urn:oasis:names:tc:SAML:2.0:nameid-format:transient
-
-
-
-
-
diff --git a/src/Helpers/IdpHelper.php b/src/Helpers/IdpHelper.php
index 23176f5..f4ca20e 100644
--- a/src/Helpers/IdpHelper.php
+++ b/src/Helpers/IdpHelper.php
@@ -6,11 +6,11 @@ class IdpHelper
{
public static function getMetadata($idpName)
{
- if (!file_exists(__DIR__ . "/../Config/idp/" . $idpName . ".xml")) {
+ if (!file_exists(__DIR__ . "/../../idp_metadata/" . $idpName . ".xml")) {
throw new \Exception("Invalid IDP Requested", 1);
}
- $xml = simplexml_load_file(__DIR__ . "/../Config/idp/" . $idpName . '.xml');
+ $xml = simplexml_load_file(__DIR__ . "/../../idp_metadata/" . $idpName . '.xml');
$metadata = array();
$metadata['idpEntityId'] = $xml->attributes()->entityID->__toString();
diff --git a/src/SpidPHP.php b/src/SpidPHP.php
index 7f99141..253fe78 100644
--- a/src/SpidPHP.php
+++ b/src/SpidPHP.php
@@ -38,7 +38,8 @@ public function getSPMetadata()
public function getSupportedIdps()
{
- return array();
+ if (is_null($this->phpSaml)) return array();
+ return $this->phpSaml->getSupportedIdps();
}
public function isAuthenticated()
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 48cac81..8d2d67b 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -46,6 +46,8 @@ private function init()
}
throw new \Exception($message, 1);
}
+ // FI suer doesn't provide for an IDP mapping, a default one is provided
+ $this->settings['idp_list'] = $this->getSupportedIdps();
$settingsHelper->updateSettings($this->settings);
}
@@ -78,15 +80,24 @@ public function getSPMetadata()
}
public function getSupportedIdps()
- {
- return array();
+ {
+ if (array_key_exists('idp_list', $this->settings) && is_array($this->settings['idp_list'])) {
+ return $this->settings['idp_list'];
+ }
+ $dir = __DIR__ . '/../../idp_metadata';
+ $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']);
- $this->authRequestID = $_SESSION['authReqID'];
}
if (isset($_SESSION) && isset($_SESSION['LogoutRequestID'])) {
@@ -114,7 +125,6 @@ public function isAuthenticated()
$this->userdata['samlNameId'] = $this->auth->getNameId();
$this->userdata['samlNameIdFormat'] = $this->auth->getNameIdFormat();
$this->userdata['samlSessionIndex'] = $this->auth->getSessionIndex();
- $_SESSION['userdata'] = $this->userdata;
}
if ($this->auth->isAuthenticated() === false) {
@@ -125,6 +135,7 @@ public function isAuthenticated()
public function login( $idpName, $redirectTo = '', $level = 1 )
{
+ $this->settings['level'] = $level;
$this->changeIdp($idpName);
if ($this->auth->isAuthenticated()) {
@@ -161,7 +172,7 @@ public function logout()
public function getAttributes()
{
- return $this->userdata;
+ return $this->userdata['attributes'];
}
}
\ No newline at end of file
From 576bc4102de6301e564bdf845a1639bd86cb7973 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 3 Aug 2018 13:05:38 +0200
Subject: [PATCH 55/69] fix exception
---
src/Config/OneloginSamlConfig.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
index 8c9fabd..62b1863 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneloginSamlConfig.php
@@ -128,7 +128,7 @@ public function updateSettings($settings) {
public function updateIdpMetadata($idpName) {
if (!array_key_exists($idpName, $this->idp_list)) {
- throw new Exception("Unsupported IDP provided", 1);
+ throw new \Exception("Unsupported IDP provided", 1);
}
$metadata = IdpHelper::getMetadata($idpName);
foreach ($metadata as $key => $value) {
From 1b423bf60ccff9489c3cd406fa9c6fd6dc777b24 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 3 Aug 2018 13:25:38 +0200
Subject: [PATCH 56/69] better init strategy
---
src/SpidPHP.php | 9 ++-------
src/Strategy/PhpSamlOneLogin.php | 9 ++++++---
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/src/SpidPHP.php b/src/SpidPHP.php
index 253fe78..53733bc 100644
--- a/src/SpidPHP.php
+++ b/src/SpidPHP.php
@@ -16,6 +16,8 @@ public function __construct($settings = null, $mode = 'onelogin')
session_start();
$this->mode = $mode;
$this->settings = $settings;
+
+ $this->initStrategy();
}
private function initStrategy($idpName = null)
@@ -32,20 +34,16 @@ private function initStrategy($idpName = null)
public function getSPMetadata()
{
- if (is_null($this->phpSaml)) $this->initStrategy();
return $this->phpSaml->getSPMetadata();
}
public function getSupportedIdps()
{
- if (is_null($this->phpSaml)) return array();
return $this->phpSaml->getSupportedIdps();
}
public function isAuthenticated()
{
- if (isset($_SESSION['idpName']) && is_null($this->phpSaml)) $this->initStrategy($_SESSION['idpName']);
- if (is_null($this->phpSaml)) return false;
return $this->phpSaml->isAuthenticated();
}
@@ -57,14 +55,11 @@ public function login( $idpName, $redirectTo = '', $level = 1 )
public function logout()
{
- if (isset($_SESSION['idpName']) && is_null($this->phpSaml)) $this->initStrategy($_SESSION['idpName']);
- if (is_null($this->phpSaml)) return false;
return $this->phpSaml->logout();
}
public function getAttributes()
{
- if (is_null($this->phpSaml)) return false;
return $this->phpSaml->getAttributes();
}
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 8d2d67b..940d4df 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -25,7 +25,7 @@ class PhpSamlOneLogin implements PhpSamlInterface
function __construct($idpName = null, $settings)
{
- $this->idpName = $idpName ?? "testenv2";
+ $this->idpName = $idpName;
$this->settings = $settings;
$this->init();
}
@@ -50,7 +50,8 @@ private function init()
$this->settings['idp_list'] = $this->getSupportedIdps();
$settingsHelper->updateSettings($this->settings);
}
-
+ reset($this->settings['idp_list']);
+ $this->idpName = is_null($this->idpName) ? key($this->settings['idp_list']) : $this->idpName;
$this->settingsHelper->updateIdpMetadata($this->idpName);
$this->oneloginSettings = new Settings($this->settingsHelper->getSettings());
$this->auth = new Auth($this->settingsHelper->getSettings());
@@ -84,6 +85,7 @@ public function getSupportedIdps()
if (array_key_exists('idp_list', $this->settings) && is_array($this->settings['idp_list'])) {
return $this->settings['idp_list'];
}
+ return array(2,3,4);
$dir = __DIR__ . '/../../idp_metadata';
$idp_files = glob( $dir . '*.{xml}', GLOB_BRACE);
$idps = array();
@@ -171,7 +173,8 @@ public function logout()
}
public function getAttributes()
- {
+ {
+ if (is_null($this->userdata) || !array_key_exists('attributes', $this->userdata)) return array();
return $this->userdata['attributes'];
}
From 8bb62a015415014d8ab160408d5795444994ba85 Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 3 Aug 2018 18:56:33 +0200
Subject: [PATCH 57/69] made project folder independant
---
example/idps.php | 1 +
example/settings.php | 3 ++-
src/Config/OneloginSamlConfig.php | 2 ++
src/Helpers/Constants.php | 6 ++++++
src/Helpers/IdpHelper.php | 6 ++++--
src/Strategy/PhpSamlOneLogin.php | 9 +++++++--
6 files changed, 22 insertions(+), 5 deletions(-)
create mode 100644 src/Helpers/Constants.php
diff --git a/example/idps.php b/example/idps.php
index 1406f0f..99a6af9 100644
--- a/example/idps.php
+++ b/example/idps.php
@@ -4,6 +4,7 @@
use SpidPHP\SpidPHP;
+
$onelogin = new SpidPHP($settings);
foreach ($onelogin->getSupportedIdps() as $key => $idp) {
diff --git a/example/settings.php b/example/settings.php
index 054c3a3..f7879f8 100644
--- a/example/settings.php
+++ b/example/settings.php
@@ -7,5 +7,6 @@
'spKeyFile' => __DIR__ . "/../sp.key",
'spCrtFile' => __DIR__ . "/../sp.crt",
'spAcsUrl' => $base."/acs.php",
- 'spSloUrl' => $base."/logout.php"
+ 'spSloUrl' => $base."/logout.php",
+ "idpMetadataFolderPath" => "idp_metadata"
];
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
index 62b1863..ed1a403 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneloginSamlConfig.php
@@ -22,11 +22,13 @@ class OneloginSamlConfig
var $idpSSO = null;
var $idpSLO = null;
var $idpCertValue = null;
+ var $idpMetadataFolderPath= null;
var $level = 1;
var $idp_list = array();
+ private $is_required = ['spBaseUrl', ];
private $is_not_updatable = ['spKeyFileValue', 'spCrtFileValue', 'idpEntityId', 'idpSSO', 'idpSLO', 'idpCertValue'];
function __construct()
diff --git a/src/Helpers/Constants.php b/src/Helpers/Constants.php
new file mode 100644
index 0000000..28278cd
--- /dev/null
+++ b/src/Helpers/Constants.php
@@ -0,0 +1,6 @@
+settings) && is_array($this->settings['idp_list'])) {
+
return $this->settings['idp_list'];
}
- return array(2,3,4);
- $dir = __DIR__ . '/../../idp_metadata';
+
+ $dir = APP_PATH . $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();
}
+ print_r($idp_files);
+ die;
return $idps;
}
From b8f7d7c4ec9f4b65b29fbfc6d34ab8a287040c4b Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 3 Aug 2018 19:20:26 +0200
Subject: [PATCH 58/69] fix root folder path
---
example/settings.php | 2 +-
src/Helpers/Constants.php | 12 +++++++++---
src/Helpers/IdpHelper.php | 6 ++----
src/Strategy/PhpSamlOneLogin.php | 4 ++--
4 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/example/settings.php b/example/settings.php
index f7879f8..0135ac0 100644
--- a/example/settings.php
+++ b/example/settings.php
@@ -8,5 +8,5 @@
'spCrtFile' => __DIR__ . "/../sp.crt",
'spAcsUrl' => $base."/acs.php",
'spSloUrl' => $base."/logout.php",
- "idpMetadataFolderPath" => "idp_metadata"
+ "idpMetadataFolderPath" => "../idp_metadata"
];
diff --git a/src/Helpers/Constants.php b/src/Helpers/Constants.php
index 28278cd..9f47c6c 100644
--- a/src/Helpers/Constants.php
+++ b/src/Helpers/Constants.php
@@ -1,6 +1,12 @@
attributes()->entityID->__toString();
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 63920fa..8c0e788 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -6,12 +6,12 @@
use SpidPHP\Helpers\ArrayHelper;
use SpidPHP\Helpers\IdpHelper;
use SpidPHP\Helpers\SpHelper;
-use const SpidPHP\Helpers\Constants\APP_PATH;
use SpidPHP\Config\OneloginSamlConfig;
use OneLogin\Saml2\Auth;
use OneLogin\Saml2\Utils;
use OneLogin\Saml2\Settings;
+use SpidPHP\Helpers\Constants;
class PhpSamlOneLogin implements PhpSamlInterface
@@ -89,7 +89,7 @@ public function getSupportedIdps()
return $this->settings['idp_list'];
}
- $dir = APP_PATH . $this->settings['idpMetadataFolderPath'];
+ $dir = Constants::APP_PATH . $this->settings['idpMetadataFolderPath'];
$idp_files = glob( $dir . '*.{xml}', GLOB_BRACE);
$idps = array();
foreach ($idp_files as $key => $value) {
From de10e762dd784f80a997cd02585cb4a3b0ff467d Mon Sep 17 00:00:00 2001
From: Lorenzo Cattaneo
Date: Fri, 3 Aug 2018 19:53:15 +0200
Subject: [PATCH 59/69] WIP : better handling of supported IDP list
---
example/idps.php | 1 -
example/settings.php | 2 +-
src/Helpers/Constants.php | 1 +
src/Helpers/PathHelper.php | 19 +++++++++++++++++++
src/Strategy/PhpSamlOneLogin.php | 6 ++----
5 files changed, 23 insertions(+), 6 deletions(-)
create mode 100644 src/Helpers/PathHelper.php
diff --git a/example/idps.php b/example/idps.php
index 99a6af9..8697ed9 100644
--- a/example/idps.php
+++ b/example/idps.php
@@ -6,7 +6,6 @@
$onelogin = new SpidPHP($settings);
-
foreach ($onelogin->getSupportedIdps() as $key => $idp) {
echo $key . ' - ' . $idp . '
';
}
\ No newline at end of file
diff --git a/example/settings.php b/example/settings.php
index 0135ac0..dd5a439 100644
--- a/example/settings.php
+++ b/example/settings.php
@@ -8,5 +8,5 @@
'spCrtFile' => __DIR__ . "/../sp.crt",
'spAcsUrl' => $base."/acs.php",
'spSloUrl' => $base."/logout.php",
- "idpMetadataFolderPath" => "../idp_metadata"
+ "idpMetadataFolderPath" => "spid-php2/idp_metadata"
];
diff --git a/src/Helpers/Constants.php b/src/Helpers/Constants.php
index 9f47c6c..e337ef9 100644
--- a/src/Helpers/Constants.php
+++ b/src/Helpers/Constants.php
@@ -3,6 +3,7 @@
namespace SpidPHP\Helpers;
class Constants {
+ // Project root folder, assuming the package has been installed with composer.
const APP_PATH = __DIR__ . '/../../../';
public static function getAppPath()
diff --git a/src/Helpers/PathHelper.php b/src/Helpers/PathHelper.php
new file mode 100644
index 0000000..baa19dd
--- /dev/null
+++ b/src/Helpers/PathHelper.php
@@ -0,0 +1,19 @@
+settings) && is_array($this->settings['idp_list'])) {
-
return $this->settings['idp_list'];
}
- $dir = Constants::APP_PATH . $this->settings['idpMetadataFolderPath'];
+ $dir = Constants::APP_PATH . PathHelper::fixPathSlashes($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();
}
- print_r($idp_files);
- die;
return $idps;
}
From cfd79633e0c21d21390ac76d7ac8548cea409bb8 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Thu, 9 Aug 2018 19:45:13 +0200
Subject: [PATCH 60/69] metadata endpoint OK
---
bin/download_idp_metadata.php | 39 +++++++++++++++++++++++++++++++
example/settings.php | 13 ++++++++++-
src/Config/OneloginSamlConfig.php | 8 +++----
src/Helpers/ArrayHelper.php | 24 -------------------
src/Helpers/Constants.php | 13 -----------
src/Helpers/IdpHelper.php | 16 ++++++++-----
src/Helpers/PathHelper.php | 19 ---------------
src/Strategy/PhpSamlOneLogin.php | 18 ++++++--------
8 files changed, 72 insertions(+), 78 deletions(-)
create mode 100755 bin/download_idp_metadata.php
delete mode 100644 src/Helpers/ArrayHelper.php
delete mode 100644 src/Helpers/Constants.php
delete mode 100644 src/Helpers/PathHelper.php
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/example/settings.php b/example/settings.php
index dd5a439..6906f82 100644
--- a/example/settings.php
+++ b/example/settings.php
@@ -8,5 +8,16 @@
'spCrtFile' => __DIR__ . "/../sp.crt",
'spAcsUrl' => $base."/acs.php",
'spSloUrl' => $base."/logout.php",
- "idpMetadataFolderPath" => "spid-php2/idp_metadata"
+ 'idpMetadataFolderPath' => "/srv/spid-php2/idp_metadata",
+ 'idpList' => array(
+ 'idp_1',
+ 'idp_2',
+ 'idp_3',
+ 'idp_4',
+ 'idp_5',
+ 'idp_6',
+ 'idp_7',
+ 'idp_8',
+ 'testenv2'
+ )
];
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
index ed1a403..a24fea9 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneloginSamlConfig.php
@@ -26,7 +26,7 @@ class OneloginSamlConfig
var $level = 1;
- var $idp_list = array();
+ var $idpList = array();
private $is_required = ['spBaseUrl', ];
private $is_not_updatable = ['spKeyFileValue', 'spCrtFileValue', 'idpEntityId', 'idpSSO', 'idpSLO', 'idpCertValue'];
@@ -129,10 +129,10 @@ public function updateSettings($settings) {
}
public function updateIdpMetadata($idpName) {
- if (!array_key_exists($idpName, $this->idp_list)) {
- throw new \Exception("Unsupported IDP provided", 1);
+ if (!in_array($idpName, $this->idpList)) {
+ throw new \Exception("Unsupported IDP $idpName", 1);
}
- $metadata = IdpHelper::getMetadata($idpName);
+ $metadata = IdpHelper::getMetadata($idpName, $this->idpMetadataFolderPath);
foreach ($metadata as $key => $value) {
if (property_exists(OneloginSamlConfig::class, $key) && strpos($key, "idp") !== false) {
$this->{$key} = $value;
diff --git a/src/Helpers/ArrayHelper.php b/src/Helpers/ArrayHelper.php
deleted file mode 100644
index 29154a0..0000000
--- a/src/Helpers/ArrayHelper.php
+++ /dev/null
@@ -1,24 +0,0 @@
- $v) {
- if (is_array($arr1[$k]) && is_array($arr2[$k])) {
- $d = array_diff_key_recursive($arr1[$k], $arr2[$k]);
-
- if ($d) {
- $diff[$k] = $d;
- }
- }
- }
-
- return $diff;
- }
-}
diff --git a/src/Helpers/Constants.php b/src/Helpers/Constants.php
deleted file mode 100644
index e337ef9..0000000
--- a/src/Helpers/Constants.php
+++ /dev/null
@@ -1,13 +0,0 @@
-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('//SingleSignOnService')[0]->attributes()->Location->__toString();
- $metadata['idpSLO'] = $xml->xpath('//SingleLogoutService')[0]->attributes()->Location->__toString();
- $metadata['idpCertValue'] = $xml->xpath('//X509Certificate')[0]->__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/PathHelper.php b/src/Helpers/PathHelper.php
deleted file mode 100644
index baa19dd..0000000
--- a/src/Helpers/PathHelper.php
+++ /dev/null
@@ -1,19 +0,0 @@
-settingsHelper = $settingsHelper;
if (!is_null($this->settings)) {
- $diff = ArrayHelper::array_diff_key_recursive($this->settings, get_object_vars($settingsHelper));
+ $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;
@@ -49,12 +46,11 @@ private function init()
}
throw new \Exception($message, 1);
}
- // FI suer doesn't provide for an IDP mapping, a default one is provided
- $this->settings['idp_list'] = $this->getSupportedIdps();
+ // if the user doesn't supply a preferred IDP, a default one is used
+ $this->settings['idpList'] = $this->getSupportedIdps();
$settingsHelper->updateSettings($this->settings);
}
- reset($this->settings['idp_list']);
- $this->idpName = is_null($this->idpName) ? key($this->settings['idp_list']) : $this->idpName;
+ $this->idpName = is_null($this->idpName) ? $this->settings['idpList'][1] : $this->idpName;
$this->settingsHelper->updateIdpMetadata($this->idpName);
$this->oneloginSettings = new Settings($this->settingsHelper->getSettings());
$this->auth = new Auth($this->settingsHelper->getSettings());
@@ -85,11 +81,11 @@ public function getSPMetadata()
public function getSupportedIdps()
{
- if (array_key_exists('idp_list', $this->settings) && is_array($this->settings['idp_list'])) {
- return $this->settings['idp_list'];
+ if (array_key_exists('idpList', $this->settings) && is_array($this->settings['idpList'])) {
+ return $this->settings['idpList'];
}
- $dir = Constants::APP_PATH . PathHelper::fixPathSlashes($this->settings['idpMetadataFolderPath']);
+ $dir = $this->settings['idpMetadataFolderPath'];
$idp_files = glob( $dir . '*.{xml}', GLOB_BRACE);
$idps = array();
foreach ($idp_files as $key => $value) {
From 5944028403b50c37ca73da9f69f53d49c089a212 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Thu, 9 Aug 2018 19:52:41 +0200
Subject: [PATCH 61/69] PSR2
---
src/Config/OneloginSamlConfig.php | 43 +++++++++++---------
src/Helpers/IdpHelper.php | 2 +-
src/Helpers/SpHelper.php | 1 -
src/SpidPHP.php | 17 ++++----
src/Strategy/Interfaces/PhpSamlInterface.php | 7 ++--
src/Strategy/PhpSamlOneLogin.php | 27 ++++++------
6 files changed, 51 insertions(+), 46 deletions(-)
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
index a24fea9..ed24845 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneloginSamlConfig.php
@@ -5,33 +5,32 @@
use SpidPHP\Helpers\SpHelper;
use SpidPHP\Helpers\IdpHelper;
-
class OneloginSamlConfig
{
// Default values SP
- var $spBaseUrl = '';
- var $spEntityId = null;
- var $spKeyFile = 'sp.key';
- var $spCrtFile = 'sp.crt';
+ public $spBaseUrl = '';
+ public $spEntityId = null;
+ public $spKeyFile = 'sp.key';
+ public $spCrtFile = 'sp.crt';
private $spKeyFileValue = null;
private $spCrtFileValue = null;
- var $spAcsUrl = null;
- var $spSloUrl = null;
+ public $spAcsUrl = null;
+ public $spSloUrl = null;
// Default values IDP
- var $idpEntityId = null;
- var $idpSSO = null;
- var $idpSLO = null;
- var $idpCertValue = null;
- var $idpMetadataFolderPath= null;
+ public $idpEntityId = null;
+ public $idpSSO = null;
+ public $idpSLO = null;
+ public $idpCertValue = null;
+ public $idpMetadataFolderPath= null;
- var $level = 1;
+ public $level = 1;
- var $idpList = array();
+ public $idpList = array();
private $is_required = ['spBaseUrl', ];
private $is_not_updatable = ['spKeyFileValue', 'spCrtFileValue', 'idpEntityId', 'idpSSO', 'idpSLO', 'idpCertValue'];
- function __construct()
+ public function __construct()
{
// Default values
$this->spAcsUrl = $this->spBaseUrl . '/index.php?acs';
@@ -108,7 +107,8 @@ public function getSettings()
);
}
- public function updateSettings($settings) {
+ public function updateSettings($settings)
+ {
foreach ($settings as $key => $value) {
if (!property_exists(OneloginSamlConfig::class, $key)) {
continue;
@@ -128,7 +128,8 @@ public function updateSettings($settings) {
return $this->getSettings();
}
- public function updateIdpMetadata($idpName) {
+ public function updateIdpMetadata($idpName)
+ {
if (!in_array($idpName, $this->idpList)) {
throw new \Exception("Unsupported IDP $idpName", 1);
}
@@ -141,11 +142,13 @@ public function updateIdpMetadata($idpName) {
return $this->getSettings();
}
- public function updateSpData($sp) {
- if (!is_array($sp))
+ public function updateSpData($sp)
+ {
+ if (!is_array($sp)) {
throw new \Exception("Invalid SP certificate data provided", 1);
+ }
- $this->spKeyFile = $sp['key'];
+ $this->spKeyFile = $sp['key'];
$this->spCrtFile = $sp['cert'];
return $this->getSettings();
diff --git a/src/Helpers/IdpHelper.php b/src/Helpers/IdpHelper.php
index f360e3a..7ce1fb0 100644
--- a/src/Helpers/IdpHelper.php
+++ b/src/Helpers/IdpHelper.php
@@ -24,4 +24,4 @@ public static function getMetadata($idpName, $folder)
return $metadata;
}
-}
\ No newline at end of file
+}
diff --git a/src/Helpers/SpHelper.php b/src/Helpers/SpHelper.php
index 8f3e0c0..fa9ce8d 100644
--- a/src/Helpers/SpHelper.php
+++ b/src/Helpers/SpHelper.php
@@ -26,4 +26,3 @@ private static function cleanOpenSsl($k)
return $ck;
}
}
-
diff --git a/src/SpidPHP.php b/src/SpidPHP.php
index 53733bc..e35a195 100644
--- a/src/SpidPHP.php
+++ b/src/SpidPHP.php
@@ -12,7 +12,7 @@ class SpidPHP implements PhpSamlInterface
private $settings = null;
public function __construct($settings = null, $mode = 'onelogin')
- {
+ {
session_start();
$this->mode = $mode;
$this->settings = $settings;
@@ -43,13 +43,15 @@ public function getSupportedIdps()
}
public function isAuthenticated()
- {
+ {
return $this->phpSaml->isAuthenticated();
}
- public function login( $idpName, $redirectTo = '', $level = 1 )
- {
- if (is_null($this->phpSaml)) $this->initStrategy($idpName);
+ public function login($idpName, $redirectTo = '', $level = 1)
+ {
+ if (is_null($this->phpSaml)) {
+ $this->initStrategy($idpName);
+ }
return $this->phpSaml->login($idpName, $redirectTo);
}
@@ -59,8 +61,7 @@ public function logout()
}
public function getAttributes()
- {
+ {
return $this->phpSaml->getAttributes();
}
-
-}
\ No newline at end of file
+}
diff --git a/src/Strategy/Interfaces/PhpSamlInterface.php b/src/Strategy/Interfaces/PhpSamlInterface.php
index d21acf3..f54bb31 100644
--- a/src/Strategy/Interfaces/PhpSamlInterface.php
+++ b/src/Strategy/Interfaces/PhpSamlInterface.php
@@ -2,11 +2,12 @@
namespace SpidPHP\Strategy\Interfaces;
-interface PhpSamlInterface {
+interface PhpSamlInterface
+{
public function getSPMetadata();
public function getSupportedIdps();
public function isAuthenticated();
- public function login( $idpName, $redirectTo = '', $level = 1 );
+ public function login($idpName, $redirectTo = '', $level = 1);
public function logout();
public function getAttributes();
-}
\ No newline at end of file
+}
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index c67d2bb..9d0da8c 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -11,7 +11,6 @@
use OneLogin\Saml2\Utils;
use OneLogin\Saml2\Settings;
-
class PhpSamlOneLogin implements PhpSamlInterface
{
private $idpName = null;
@@ -23,9 +22,9 @@ class PhpSamlOneLogin implements PhpSamlInterface
private $oneloginSettings;
private $userdata;
- function __construct($idpName = null, $settings)
+ public function __construct($settings, $idpName = null)
{
- $this->idpName = $idpName;
+ $this->idpName = $idpName;
$this->settings = $settings;
$this->init();
}
@@ -40,7 +39,9 @@ private function init()
$message = "The following keys are invalid for the provided settings array: ";
$first = true;
foreach ($diff as $key => $value) {
- if ($first) $message .= $key;
+ if ($first) {
+ $message .= $key;
+ }
$first = false;
$message .= ", " . $key;
}
@@ -80,13 +81,13 @@ public function getSPMetadata()
}
public function getSupportedIdps()
- {
+ {
if (array_key_exists('idpList', $this->settings) && is_array($this->settings['idpList'])) {
- return $this->settings['idpList'];
+ return $this->settings['idpList'];
}
$dir = $this->settings['idpMetadataFolderPath'];
- $idp_files = glob( $dir . '*.{xml}', GLOB_BRACE);
+ $idp_files = glob($dir . '*.{xml}', GLOB_BRACE);
$idps = array();
foreach ($idp_files as $key => $value) {
$xml = simplexml_load_file($value);
@@ -126,7 +127,6 @@ public function isAuthenticated()
$this->userdata['samlNameId'] = $this->auth->getNameId();
$this->userdata['samlNameIdFormat'] = $this->auth->getNameIdFormat();
$this->userdata['samlSessionIndex'] = $this->auth->getSessionIndex();
-
}
if ($this->auth->isAuthenticated() === false) {
return false;
@@ -134,7 +134,7 @@ public function isAuthenticated()
return true;
}
- public function login( $idpName, $redirectTo = '', $level = 1 )
+ public function login($idpName, $redirectTo = '', $level = 1)
{
$this->settings['level'] = $level;
$this->changeIdp($idpName);
@@ -172,9 +172,10 @@ public function logout()
}
public function getAttributes()
- {
- if (is_null($this->userdata) || !array_key_exists('attributes', $this->userdata)) return array();
+ {
+ if (is_null($this->userdata) || !array_key_exists('attributes', $this->userdata)) {
+ return array();
+ }
return $this->userdata['attributes'];
}
-
-}
\ No newline at end of file
+}
From 2466c9988bb521423f03f101dd44ec25957c723f Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Fri, 10 Aug 2018 06:14:56 +0200
Subject: [PATCH 62/69] cleanup and complete round-trip
---
example/logout.php | 3 ++-
example/settings.php | 13 +++++++------
src/Config/OneloginSamlConfig.php | 4 ++--
src/SpidPHP.php | 4 ++--
src/Strategy/PhpSamlOneLogin.php | 6 +++---
5 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/example/logout.php b/example/logout.php
index 6f56ac5..75fd166 100644
--- a/example/logout.php
+++ b/example/logout.php
@@ -14,5 +14,6 @@
if ($onelogin->isAuthenticated()) {
$onelogin->logout();
} else {
- echo "Logged out!";
+ echo "Logged out!";
+ echo 'Go back
';
}
diff --git a/example/settings.php b/example/settings.php
index 6906f82..c8a0297 100644
--- a/example/settings.php
+++ b/example/settings.php
@@ -1,14 +1,15 @@
$base,
- 'spEntityId' => $base."/metadata.php",
- 'spKeyFile' => __DIR__ . "/../sp.key",
- 'spCrtFile' => __DIR__ . "/../sp.crt",
- 'spAcsUrl' => $base."/acs.php",
- 'spSloUrl' => $base."/logout.php",
- 'idpMetadataFolderPath' => "/srv/spid-php2/idp_metadata",
+ 'spEntityId' => $base,
+ 'spKeyFile' => $home . "/sp.key",
+ 'spCrtFile' => $home . "/sp.crt",
+ 'spAcsUrl' => $base . "/acs.php",
+ 'spSloUrl' => $base . "/logout.php",
+ 'idpMetadataFolderPath' => $home . "/idp_metadata",
'idpList' => array(
'idp_1',
'idp_2',
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
index ed24845..4da6c0b 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneloginSamlConfig.php
@@ -27,7 +27,7 @@ class OneloginSamlConfig
public $idpList = array();
- private $is_required = ['spBaseUrl', ];
+ private $is_required = ['spBaseUrl'];
private $is_not_updatable = ['spKeyFileValue', 'spCrtFileValue', 'idpEntityId', 'idpSSO', 'idpSLO', 'idpCertValue'];
public function __construct()
@@ -35,7 +35,7 @@ public function __construct()
// Default values
$this->spAcsUrl = $this->spBaseUrl . '/index.php?acs';
$this->spSloUrl = $this->spBaseUrl . '/index.php?sls';
- $this->spEntityId = $this->spBaseUrl . '/metadata.php';
+ $this->spEntityId = $this->spBaseUrl;
}
public function getSettings()
diff --git a/src/SpidPHP.php b/src/SpidPHP.php
index e35a195..2d91b67 100644
--- a/src/SpidPHP.php
+++ b/src/SpidPHP.php
@@ -24,10 +24,10 @@ private function initStrategy($idpName = null)
{
switch ($this->mode) {
case 'onelogin':
- $this->phpSaml = new PhpSamlOneLogin($idpName, $this->settings);
+ $this->phpSaml = new PhpSamlOneLogin($this->settings, $idpName);
break;
default:
- $this->phpSaml = new PhpSamlOneLogin($idpName, $this->settings);
+ $this->phpSaml = new PhpSamlOneLogin($this->settings, $idpName);
break;
}
}
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 9d0da8c..8e148db 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -51,7 +51,7 @@ private function init()
$this->settings['idpList'] = $this->getSupportedIdps();
$settingsHelper->updateSettings($this->settings);
}
- $this->idpName = is_null($this->idpName) ? $this->settings['idpList'][1] : $this->idpName;
+ $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());
@@ -173,9 +173,9 @@ public function logout()
public function getAttributes()
{
- if (is_null($this->userdata) || !array_key_exists('attributes', $this->userdata)) {
+ if (is_null($this->userdata) || !array_key_exists('samlUserdata', $this->userdata)) {
return array();
}
- return $this->userdata['attributes'];
+ return $this->userdata['samlUserdata'];
}
}
From d3ce513cb9934772e6f62d09f6eac119fe0a8ccd Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Fri, 10 Aug 2018 06:45:35 +0200
Subject: [PATCH 63/69] make patches generic
---
AuthnRequest.diff | 2 +-
LogoutRequest.diff | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/AuthnRequest.diff b/AuthnRequest.diff
index e3265b4..2aea923 100644
--- a/AuthnRequest.diff
+++ b/AuthnRequest.diff
@@ -10,4 +10,4 @@
---
> AssertionConsumerServiceIndex="1"
> AttributeConsumingServiceIndex="1">
-> {$spEntityId}
+> {$spEntityId}
diff --git a/LogoutRequest.diff b/LogoutRequest.diff
index 782267d..8e9f466 100644
--- a/LogoutRequest.diff
+++ b/LogoutRequest.diff
@@ -1,4 +1,4 @@
128c128
< {$spEntityId}
---
-> {$spEntityId}
+> {$spEntityId}
From e1152a94101ae5ed6ce04754445867b90548ab6a Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Fri, 10 Aug 2018 06:46:06 +0200
Subject: [PATCH 64/69] unpack atttributes if they are sent nack as arrays
---
src/Strategy/PhpSamlOneLogin.php | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/PhpSamlOneLogin.php
index 8e148db..adf858f 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/PhpSamlOneLogin.php
@@ -127,6 +127,11 @@ public function isAuthenticated()
$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;
From ae88827df6a2eced3208b99aa9e76d587366abb7 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Fri, 10 Aug 2018 07:08:22 +0200
Subject: [PATCH 65/69] document settings and get rid of spBaseUrl
---
example/settings.php | 15 ++++++++-------
src/Config/OneloginSamlConfig.php | 8 +++-----
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/example/settings.php b/example/settings.php
index c8a0297..d023536 100644
--- a/example/settings.php
+++ b/example/settings.php
@@ -3,13 +3,14 @@
$base = "http://sp2.simevo.com:8000";
$home = "/srv/spid-php2";
$settings = [
- 'spBaseUrl' => $base,
- 'spEntityId' => $base,
- 'spKeyFile' => $home . "/sp.key",
- 'spCrtFile' => $home . "/sp.crt",
- 'spAcsUrl' => $base . "/acs.php",
- 'spSloUrl' => $base . "/logout.php",
- 'idpMetadataFolderPath' => $home . "/idp_metadata",
+ 'spEntityId' => $base, // preferred: https protocol, no path, no trailing slash
+ 'spAcsUrl' => $base . "/acs.php", // full url
+ 'spSloUrl' => $base . "/logout.php", // full url
+ 'spKeyFile' => $home . "/sp.key", // full path
+ 'spCrtFile' => $home . "/sp.crt", // full path
+ 'idpMetadataFolderPath' => $home . "/idp_metadata", // full 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',
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneloginSamlConfig.php
index 4da6c0b..1c29431 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneloginSamlConfig.php
@@ -8,7 +8,6 @@
class OneloginSamlConfig
{
// Default values SP
- public $spBaseUrl = '';
public $spEntityId = null;
public $spKeyFile = 'sp.key';
public $spCrtFile = 'sp.crt';
@@ -27,15 +26,14 @@ class OneloginSamlConfig
public $idpList = array();
- private $is_required = ['spBaseUrl'];
+ private $is_required = ['spEntityId'];
private $is_not_updatable = ['spKeyFileValue', 'spCrtFileValue', 'idpEntityId', 'idpSSO', 'idpSLO', 'idpCertValue'];
public function __construct()
{
// Default values
- $this->spAcsUrl = $this->spBaseUrl . '/index.php?acs';
- $this->spSloUrl = $this->spBaseUrl . '/index.php?sls';
- $this->spEntityId = $this->spBaseUrl;
+ $this->spAcsUrl = $this->spEntityId . '/index.php?acs';
+ $this->spSloUrl = $this->spEntityId . '/index.php?sls';
}
public function getSettings()
From 2c3448fb65c5fc12e4faef75d3642091dd6aab8a Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Fri, 10 Aug 2018 07:16:59 +0200
Subject: [PATCH 66/69] polish example
---
example/acs.php | 2 --
example/index.php | 1 +
example/login.php | 3 +--
3 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/example/acs.php b/example/acs.php
index e83c9c3..7338e65 100644
--- a/example/acs.php
+++ b/example/acs.php
@@ -23,5 +23,3 @@
echo "not logged in !" . PHP_EOL;
echo 'Login
';
}
-
-
diff --git a/example/index.php b/example/index.php
index f9a3c71..5681d2b 100644
--- a/example/index.php
+++ b/example/index.php
@@ -2,5 +2,6 @@
echo '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
index 3f24a21..6b91adb 100644
--- a/example/login.php
+++ b/example/login.php
@@ -14,6 +14,5 @@
if ($onelogin->isAuthenticated() === false) {
$onelogin->login("testenv2");
} else {
- echo "Already logged in!";
+ echo "Already logged in!";
}
-
From ea7ef30b9ef0a1ccfc5575d87657ea93d1e04a21 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Fri, 10 Aug 2018 07:57:50 +0200
Subject: [PATCH 67/69] we have no scripts yet
---
composer.json | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/composer.json b/composer.json
index 9ddc39e..bd78975 100644
--- a/composer.json
+++ b/composer.json
@@ -4,18 +4,9 @@
"onelogin/php-saml": "3.0.0.x-dev",
"squizlabs/php_codesniffer": "*"
},
-
- "scripts": {
- "post-install-cmd": [
- "setup\\Configuration::setup"
- ],
- "post-update-cmd": [
- "setup\\Configuration::setup"
- ]
- },
"autoload": {
"psr-4": {
"SpidPHP\\": "src/"
}
}
-}
+}
\ No newline at end of file
From 72926874d48af2baba032f1cfe735400f78ebd08 Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Fri, 10 Aug 2018 07:59:44 +0200
Subject: [PATCH 68/69] rename namespace and classes; move SpInterface.php to
src/Interfaces
---
composer.json | 2 +-
example/acs.php | 8 ++----
example/idps.php | 9 ++----
example/login.php | 8 ++----
example/logout.php | 8 ++----
example/metadata.php | 6 ++--
example/settings.php | 1 +
...loginSamlConfig.php => OneLoginConfig.php} | 14 +++++-----
src/Helpers/IdpHelper.php | 2 +-
src/Helpers/SpHelper.php | 2 +-
.../SpInterface.php} | 4 +--
src/{SpidPHP.php => Sp.php} | 28 +++++++++----------
.../{PhpSamlOneLogin.php => SpOneLogin.php} | 14 +++++-----
13 files changed, 48 insertions(+), 58 deletions(-)
rename src/Config/{OneloginSamlConfig.php => OneLoginConfig.php} (93%)
rename src/{Strategy/Interfaces/PhpSamlInterface.php => Interfaces/SpInterface.php} (79%)
rename src/{SpidPHP.php => Sp.php} (55%)
rename src/Strategy/{PhpSamlOneLogin.php => SpOneLogin.php} (95%)
diff --git a/composer.json b/composer.json
index bd78975..cf8a5be 100644
--- a/composer.json
+++ b/composer.json
@@ -6,7 +6,7 @@
},
"autoload": {
"psr-4": {
- "SpidPHP\\": "src/"
+ "Spid\\": "src/"
}
}
}
\ No newline at end of file
diff --git a/example/acs.php b/example/acs.php
index 7338e65..b38e009 100644
--- a/example/acs.php
+++ b/example/acs.php
@@ -7,12 +7,10 @@
require_once(__DIR__ . "/../vendor/autoload.php");
require_once(__DIR__ . "/settings.php");
-use SpidPHP\SpidPHP;
+$sp = new Spid\Sp($settings);
-$onelogin = new SpidPHP($settings);
-
-if ($onelogin->isAuthenticated()) {
- $attributes = $onelogin->getAttributes();
+if ($sp->isAuthenticated()) {
+ $attributes = $sp->getAttributes();
echo "logged in !" . PHP_EOL;
foreach ($attributes as $key => $attribute) {
echo $key .": " . $attribute . "
";
diff --git a/example/idps.php b/example/idps.php
index 8697ed9..d1e5a69 100644
--- a/example/idps.php
+++ b/example/idps.php
@@ -2,10 +2,7 @@
require_once(__DIR__ . "/../vendor/autoload.php");
require_once(__DIR__ . "/settings.php");
-use SpidPHP\SpidPHP;
-
-
-$onelogin = new SpidPHP($settings);
-foreach ($onelogin->getSupportedIdps() as $key => $idp) {
+$sp = new Spid\Sp($settings);
+foreach ($sp->getSupportedIdps() as $key => $idp) {
echo $key . ' - ' . $idp . '
';
-}
\ No newline at end of file
+}
diff --git a/example/login.php b/example/login.php
index 6b91adb..0727e68 100644
--- a/example/login.php
+++ b/example/login.php
@@ -7,12 +7,10 @@
require_once(__DIR__ . "/../vendor/autoload.php");
require_once(__DIR__ . "/settings.php");
-use SpidPHP\SpidPHP;
+$sp = new Spid\Sp($settings);
-$onelogin = new SpidPHP($settings);
-
-if ($onelogin->isAuthenticated() === false) {
- $onelogin->login("testenv2");
+if ($sp->isAuthenticated() === false) {
+ $sp->login("testenv2");
} else {
echo "Already logged in!";
}
diff --git a/example/logout.php b/example/logout.php
index 75fd166..038c2c4 100644
--- a/example/logout.php
+++ b/example/logout.php
@@ -7,12 +7,10 @@
require_once(__DIR__ . "/../vendor/autoload.php");
require_once(__DIR__ . "/settings.php");
-use SpidPHP\SpidPHP;
+$sp = new Spid\Sp($settings);
-$onelogin = new SpidPHP($settings);
-
-if ($onelogin->isAuthenticated()) {
- $onelogin->logout();
+if ($sp->isAuthenticated()) {
+ $sp->logout();
} else {
echo "Logged out!";
echo 'Go back
';
diff --git a/example/metadata.php b/example/metadata.php
index 3358573..f93d22a 100644
--- a/example/metadata.php
+++ b/example/metadata.php
@@ -7,11 +7,9 @@
require_once(__DIR__ . "/../vendor/autoload.php");
require_once(__DIR__ . "/settings.php");
-use SpidPHP\SpidPHP;
+$sp = new Spid\Sp($settings);
-$onelogin = new SpidPHP($settings);
-
-$metadata = $onelogin->getSPMetadata();
+$metadata = $sp->getSPMetadata();
header('Content-Type: text/xml');
echo $metadata;
diff --git a/example/settings.php b/example/settings.php
index d023536..6a6355b 100644
--- a/example/settings.php
+++ b/example/settings.php
@@ -23,3 +23,4 @@
'testenv2'
)
];
+
diff --git a/src/Config/OneloginSamlConfig.php b/src/Config/OneLoginConfig.php
similarity index 93%
rename from src/Config/OneloginSamlConfig.php
rename to src/Config/OneLoginConfig.php
index 1c29431..f56cafa 100644
--- a/src/Config/OneloginSamlConfig.php
+++ b/src/Config/OneLoginConfig.php
@@ -1,11 +1,11 @@
$value) {
- if (!property_exists(OneloginSamlConfig::class, $key)) {
+ if (!property_exists(OneLoginConfig::class, $key)) {
continue;
}
if (in_array($key, $this->is_not_updatable)) {
@@ -119,7 +119,7 @@ public function updateSettings($settings)
}
// 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 and .cert files is invalid", 1);
+ 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);
@@ -133,7 +133,7 @@ public function updateIdpMetadata($idpName)
}
$metadata = IdpHelper::getMetadata($idpName, $this->idpMetadataFolderPath);
foreach ($metadata as $key => $value) {
- if (property_exists(OneloginSamlConfig::class, $key) && strpos($key, "idp") !== false) {
+ if (property_exists(OneLoginConfig::class, $key) && strpos($key, "idp") !== false) {
$this->{$key} = $value;
}
}
diff --git a/src/Helpers/IdpHelper.php b/src/Helpers/IdpHelper.php
index 7ce1fb0..1b5d263 100644
--- a/src/Helpers/IdpHelper.php
+++ b/src/Helpers/IdpHelper.php
@@ -1,6 +1,6 @@
mode) {
case 'onelogin':
- $this->phpSaml = new PhpSamlOneLogin($this->settings, $idpName);
+ $this->strategy = new SpOneLogin($this->settings, $idpName);
break;
default:
- $this->phpSaml = new PhpSamlOneLogin($this->settings, $idpName);
+ $this->strategy = new SpOneLogin($this->settings, $idpName);
break;
}
}
public function getSPMetadata()
{
- return $this->phpSaml->getSPMetadata();
+ return $this->strategy->getSPMetadata();
}
public function getSupportedIdps()
{
- return $this->phpSaml->getSupportedIdps();
+ return $this->strategy->getSupportedIdps();
}
public function isAuthenticated()
{
- return $this->phpSaml->isAuthenticated();
+ return $this->strategy->isAuthenticated();
}
public function login($idpName, $redirectTo = '', $level = 1)
{
- if (is_null($this->phpSaml)) {
+ if (is_null($this->strategy)) {
$this->initStrategy($idpName);
}
- return $this->phpSaml->login($idpName, $redirectTo);
+ return $this->strategy->login($idpName, $redirectTo);
}
public function logout()
{
- return $this->phpSaml->logout();
+ return $this->strategy->logout();
}
public function getAttributes()
{
- return $this->phpSaml->getAttributes();
+ return $this->strategy->getAttributes();
}
}
diff --git a/src/Strategy/PhpSamlOneLogin.php b/src/Strategy/SpOneLogin.php
similarity index 95%
rename from src/Strategy/PhpSamlOneLogin.php
rename to src/Strategy/SpOneLogin.php
index adf858f..b56508d 100644
--- a/src/Strategy/PhpSamlOneLogin.php
+++ b/src/Strategy/SpOneLogin.php
@@ -1,17 +1,17 @@
settingsHelper = $settingsHelper;
if (!is_null($this->settings)) {
$diff = array_diff_key($this->settings, get_object_vars($settingsHelper));
From 10df3f7c9e3de39f085801332adae4c56ce8740d Mon Sep 17 00:00:00 2001
From: Paolo Greppi
Date: Fri, 10 Aug 2018 16:21:02 +0200
Subject: [PATCH 69/69] move to Italia\Spid2 namespace; move idp_metadata
inside example; brush up README
---
.gitignore | 19 +-
Makefile | 8 +-
README.md | 175 +++++++++++++-----
composer.json | 8 +-
composer.lock | 7 +-
example/acs.php | 6 +-
.../idp_metadata}/put_idp_metadata_here | 0
example/idps.php | 4 +-
example/login.php | 6 +-
example/logout.php | 6 +-
example/metadata.php | 6 +-
example/settings.php | 11 +-
images/screencast.gif | Bin 0 -> 448258 bytes
src/Config/OneLoginConfig.php | 6 +-
src/Helpers/IdpHelper.php | 2 +-
src/Helpers/SpHelper.php | 2 +-
src/Interfaces/SpInterface.php | 2 +-
src/Sp.php | 7 +-
src/Strategy/SpOneLogin.php | 12 +-
19 files changed, 173 insertions(+), 114 deletions(-)
rename {idp_metadata => example/idp_metadata}/put_idp_metadata_here (100%)
create mode 100644 images/screencast.gif
diff --git a/.gitignore b/.gitignore
index 1d93f62..cb2c4db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,16 +1,9 @@
-sp.key
-sp.crt
-vendor
-tmp
-www/settings.php
-www2/settings.php
-config.yaml
.directory
-AuthnRequest.patched
-LogoutRequest.patched
.vscode
.DS_Store
-
-src/Config/idp/*.xml
-
-idp_metadata/*.xml
\ No newline at end of file
+AuthnRequest.patched
+LogoutRequest.patched
+vendor
+example/sp.key
+example/sp.crt
+example/idp_metadata/*.xml
diff --git a/Makefile b/Makefile
index ee5440e..e78cd76 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-all: sp.key AuthnRequest.patched LogoutRequest.patched
+all: example/sp.key AuthnRequest.patched LogoutRequest.patched
AuthnRequest.patched: TO_PATCH:=vendor/onelogin/php-saml/src/Saml2/AuthnRequest.php
AuthnRequest.patched: AuthnRequest.diff
@@ -12,10 +12,12 @@ LogoutRequest.patched: LogoutRequest.diff
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 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 c543283..dd3f84a 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,30 @@
+
+
+[![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).
-Work in progress. Do not merge this branch.
+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.
-Software Development Kit (SDK) for easy SPID SSO integration based on [php-saml](https://github.com/onelogin/php-saml).
+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).
-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.
+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
-Alternative SDK: [spid-php](https://github.com/italia/spid-php) based on [SimpleSAMLphp](https://simplesamlphp.org/).
+Alternatives for other languages:
+- [spid-perl](https://github.com/italia/spid-perl)
+- [spid-ruby](https://github.com/italia/spid-ruby)
-## Features
+## 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|
|:---|:---|:---|
@@ -75,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/composer.json b/composer.json
index cf8a5be..50f2290 100644
--- a/composer.json
+++ b/composer.json
@@ -1,12 +1,14 @@
{
"name": "italia/spid-php2",
"require": {
- "onelogin/php-saml": "3.0.0.x-dev",
- "squizlabs/php_codesniffer": "*"
+ "onelogin/php-saml": "3.0.0.x-dev"
+ },
+ "require-dev": {
+ "squizlabs/php_codesniffer": "^3.3"
},
"autoload": {
"psr-4": {
- "Spid\\": "src/"
+ "Italia\\Spid2\\": "src/"
}
}
}
\ No newline at end of file
diff --git a/composer.lock b/composer.lock
index b2aabb3..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": "9c614b6245789a0e2cf885b1e6fc7014",
+ "content-hash": "0e934f11b83adea144b2a84c424aaf82",
"packages": [
{
"name": "onelogin/php-saml",
@@ -95,7 +95,9 @@
"xmldsig"
],
"time": "2017-08-31T09:27:07+00:00"
- },
+ }
+ ],
+ "packages-dev": [
{
"name": "squizlabs/php_codesniffer",
"version": "3.3.1",
@@ -148,7 +150,6 @@
"time": "2018-07-26T23:47:18+00:00"
}
],
- "packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
diff --git a/example/acs.php b/example/acs.php
index b38e009..e10fc2d 100644
--- a/example/acs.php
+++ b/example/acs.php
@@ -1,13 +1,9 @@
isAuthenticated()) {
$attributes = $sp->getAttributes();
diff --git a/idp_metadata/put_idp_metadata_here b/example/idp_metadata/put_idp_metadata_here
similarity index 100%
rename from idp_metadata/put_idp_metadata_here
rename to example/idp_metadata/put_idp_metadata_here
diff --git a/example/idps.php b/example/idps.php
index d1e5a69..78793b7 100644
--- a/example/idps.php
+++ b/example/idps.php
@@ -1,8 +1,10 @@
getSupportedIdps() as $key => $idp) {
echo $key . ' - ' . $idp . '
';
}
diff --git a/example/login.php b/example/login.php
index 0727e68..ea97e8e 100644
--- a/example/login.php
+++ b/example/login.php
@@ -1,13 +1,9 @@
isAuthenticated() === false) {
$sp->login("testenv2");
diff --git a/example/logout.php b/example/logout.php
index 038c2c4..293c6ad 100644
--- a/example/logout.php
+++ b/example/logout.php
@@ -1,13 +1,9 @@
isAuthenticated()) {
$sp->logout();
diff --git a/example/metadata.php b/example/metadata.php
index f93d22a..f752505 100644
--- a/example/metadata.php
+++ b/example/metadata.php
@@ -1,13 +1,9 @@
getSPMetadata();
diff --git a/example/settings.php b/example/settings.php
index 6a6355b..a7592b6 100644
--- a/example/settings.php
+++ b/example/settings.php
@@ -1,14 +1,14 @@
$base, // preferred: https protocol, no path, no trailing slash
'spAcsUrl' => $base . "/acs.php", // full url
'spSloUrl' => $base . "/logout.php", // full url
- 'spKeyFile' => $home . "/sp.key", // full path
- 'spCrtFile' => $home . "/sp.crt", // full path
- 'idpMetadataFolderPath' => $home . "/idp_metadata", // full path
+ '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(
@@ -23,4 +23,3 @@
'testenv2'
)
];
-
diff --git a/images/screencast.gif b/images/screencast.gif
new file mode 100644
index 0000000000000000000000000000000000000000..daed10e98df533d0a02025fa764715b3c2fe9560
GIT binary patch
literal 448258
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