From: Vincent Vanwaelscappel Date: Tue, 22 Mar 2022 17:24:02 +0000 (+0100) Subject: wait #5074 @3 X-Git-Url: http://git.cubedesigners.com/?a=commitdiff_plain;h=f3a3fa1661fbe5d231c9698875983aabc9586be8;p=fluidbook-hosting.git wait #5074 @3 --- diff --git a/VacheronSSO/.htaccess b/VacheronSSO/.htaccess index e021dea..2731613 100644 --- a/VacheronSSO/.htaccess +++ b/VacheronSSO/.htaccess @@ -1,6 +1,4 @@ RewriteEngine on RewriteBase / -RewriteCond %{HTTP_HOST} hosting.fluidbook.com -RewriteRule ^(.*)$ https://cabinotiers.vacheron-constantin.com/$1 [R=301,L] -RewriteRule ^_secure.php$ - [L] -RewriteRule ^.*$ _secure.php [L,QSA] \ No newline at end of file +RewriteCond %{HTTP_HOST} "^hosting.fluidbook.com" +RewriteRule ^(.*)$ https://cabinotiers.vacheron-constantin.com/$1 [R=301,L] \ No newline at end of file diff --git a/VacheronSSO/_checksso.php b/VacheronSSO/_checksso.php new file mode 100644 index 0000000..9768254 --- /dev/null +++ b/VacheronSSO/_checksso.php @@ -0,0 +1,5 @@ + [['logged-in' => !$needsAuth,'session'=>print_r($_SESSION,true)]]])); diff --git a/VacheronSSO/_secure.php b/VacheronSSO/_secure.php deleted file mode 100644 index 0f1816a..0000000 --- a/VacheronSSO/_secure.php +++ /dev/null @@ -1,275 +0,0 @@ - [ - // Identifier of the SP entity (must be a URI) - 'entityId' => $base, - // Specifies info about where and how the message MUST be - // returned to the requester, in this case our SP. - 'assertionConsumerService' => array( - // URL Location where the from the IdP will be returned - 'url' => $url, - // SAML protocol binding to be used when returning the - // message. Onelogin Toolkit supports for this endpoint the - // HTTP-POST binding only - 'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', - ), -// // If you need to specify requested attributes, set a -// // attributeConsumingService. nameFormat, attributeValue and -// // friendlyName can be omitted. Otherwise remove this section. -// "attributeConsumingService" => array( -// "serviceName" => "SP test", -// "serviceDescription" => "Test Service", -// "requestedAttributes" => array( -// array( -// "name" => "", -// "isRequired" => false, -// "nameFormat" => "", -// "friendlyName" => "", -// "attributeValue" => "" -// ) -// ) -// ), -// // Specifies info about where and how the message MUST be -// // returned to the requester, in this case our SP. -// 'singleLogoutService' => array( -// // URL Location where the from the IdP will be returned -// 'url' => '', -// // SAML protocol binding to be used when returning the -// // message. Onelogin Toolkit supports for this endpoint the -// // HTTP-Redirect binding only -// 'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', -// ), -// // Specifies constraints on the name identifier to be used to -// // represent the requested subject. -// // Take a look on lib/Saml2/Constants.php to see the NameIdFormat supported -// 'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified', -// -// // Usually x509cert and privateKey of the SP are provided by files placed at -// // the certs folder. But we can also provide them with the following parameters -// 'x509cert' => '', -// 'privateKey' => '', -// -// /* -// * Key rollover -// * If you plan to update the SP x509cert and privateKey -// * you can define here the new x509cert and it will be -// * published on the SP metadata so Identity Providers can -// * read them and get ready for rollover. -// */ -// // 'x509certNew' => '', - ], - 'idp' => [ - 'entityId' => $metadata['EntityDescriptor']['@entityID'], - 'singleSignOnService' => [ - 'url' => $metadata['EntityDescriptor']['IDPSSODescriptor']['SingleSignOnService'][0]['@Location'], - ], - 'x509cert' => $metadata['EntityDescriptor']['IDPSSODescriptor']['KeyDescriptor']['KeyInfo']['X509Data']['X509Certificate'], - ]]; - - try { - $auth = new \OneLogin\Saml2\Auth($samlsettings); - } catch (Exception $e) { - http_response_code(500); - print_r($e); - die('an error occured'); - } - - if (!empty($_POST['SAMLResponse']) && !empty($_POST['RelayState'])) { - $auth->processResponse(null); - - $errors = $auth->getErrors(); - if (empty($errors)) { - // user has authenticated successfully - $needsAuth = false; - $_SESSION['samlUserdata'] = $auth->getAttributes(); - $_SESSION['samlOK'] = true; - session_write_close(); - file_put_contents($logdir.'ok.' . $t . '.log', print_r($_SESSION, true)); - file_put_contents($logdir. 'xml.' . $t . '.log', $auth->getLastResponseXML()); - - if ($_POST['RelayState'] !== $base) { - header('Location: ' . $_POST['RelayState'], true); - exit; - } - - } else { - file_put_contents($logdir.'err.' . $t . '.log', print_r($errors, true) . "\n\n--\n\n" . print_r($auth->getLastErrorReason(), true) . "\n\n--\n\n" . print_r($auth->getLastErrorException(), true)); - } - } - - if ($needsAuth) { - if ($index) { - $auth->login(); - } else { - http_response_code(403); - } - exit; - } -} - - -if (!file_exists($file)) { - http_response_code(404); - exit; -} - -$e = explode('.', $file); -$ext = mb_strtolower(array_pop($e)); -require_once "_mime.php"; -if (isset($mimes['mimes'][$ext])) { - $mime = $mimes['mimes'][$ext][0]; -} else { - $mime = mime_content_type($file); -} - -header('Content-Type: ' . $mime); -header('Content-Length: ' . filesize($file)); -header("X-Sendfile: $file"); - -function xmlToArray($xml, $options = array()) -{ - $defaults = array( - 'namespaceSeparator' => ':',//you may want this to be something other than a colon - 'attributePrefix' => '@', //to distinguish between attributes and nodes with the same name - 'alwaysArray' => array(), //array of xml tag names which should always become arrays - 'autoArray' => true, //only create arrays for tags which appear more than once - 'textContent' => '$', //key used for the text content of elements - 'autoText' => true, //skip textContent key if node has no attributes or child nodes - 'keySearch' => false, //optional search and replace on tag and attribute names - 'keyReplace' => false //replace values for above search values (as passed to str_replace()) - ); - $options = array_merge($defaults, $options); - $namespaces = $xml->getDocNamespaces(true); - $namespaces[''] = null; //add base (empty) namespace - - //get attributes from all namespaces - $attributesArray = array(); - foreach ($namespaces as $prefix => $namespace) { - foreach ($xml->attributes($namespace) as $attributeName => $attribute) { - //replace characters in attribute name - if ($options['keySearch']) $attributeName = - str_replace($options['keySearch'], $options['keyReplace'], $attributeName); - $attributeKey = $options['attributePrefix'] - . ($prefix ? $prefix . $options['namespaceSeparator'] : '') - . $attributeName; - $attributesArray[$attributeKey] = (string)$attribute; - } - } - - //get child nodes from all namespaces - $tagsArray = array(); - foreach ($namespaces as $prefix => $namespace) { - foreach ($xml->children($namespace) as $childXml) { - //recurse into child nodes - $childArray = xmlToArray($childXml, $options); - list($childTagName, $childProperties) = each($childArray); - - //replace characters in tag name - if ($options['keySearch']) $childTagName = - str_replace($options['keySearch'], $options['keyReplace'], $childTagName); - //add namespace prefix, if any - if ($prefix) $childTagName = $prefix . $options['namespaceSeparator'] . $childTagName; - - if (!isset($tagsArray[$childTagName])) { - //only entry with this key - //test if tags of this type should always be arrays, no matter the element count - $tagsArray[$childTagName] = - in_array($childTagName, $options['alwaysArray']) || !$options['autoArray'] - ? array($childProperties) : $childProperties; - } elseif ( - is_array($tagsArray[$childTagName]) && array_keys($tagsArray[$childTagName]) - === range(0, count($tagsArray[$childTagName]) - 1) - ) { - //key already exists and is integer indexed array - $tagsArray[$childTagName][] = $childProperties; - } else { - //key exists so convert to integer indexed array with previous value in position 0 - $tagsArray[$childTagName] = array($tagsArray[$childTagName], $childProperties); - } - } - } - - //get text content of node - $textContentArray = array(); - $plainText = trim((string)$xml); - if ($plainText !== '') $textContentArray[$options['textContent']] = $plainText; - - //stick it all together - $propertiesArray = !$options['autoText'] || $attributesArray || $tagsArray || ($plainText === '') - ? array_merge($attributesArray, $tagsArray, $textContentArray) : $plainText; - - //return node as array - return array( - $xml->getName() => $propertiesArray - ); -} - -function getMetadata() -{ - global $metadata; - $limit = time() - 14400; - $cachefile = __DIR__ . '/_metadata'; - - if (!file_exists($cachefile) || filesize($cachefile) <= 20 || filemtime($cachefile) < $limit) { - $client = new Client(); - $response = $client->get($metadata, ['timeout' => 30]); - $c = $response->getBody()->getContents(); - - if (!$c) { - return json_decode(file_get_contents($cachefile), true); - } - - $xml = simplexml_load_string($c); - - $metadata = xmlToArray($xml); - file_put_contents($cachefile, json_encode($metadata)); - return $metadata; - } else { - return json_decode(file_get_contents($cachefile), true); - } - -} \ No newline at end of file diff --git a/VacheronSSO/_sso.php b/VacheronSSO/_sso.php new file mode 100644 index 0000000..ca2123f --- /dev/null +++ b/VacheronSSO/_sso.php @@ -0,0 +1,246 @@ + [ + // Identifier of the SP entity (must be a URI) + 'entityId' => $base, + // Specifies info about where and how the message MUST be + // returned to the requester, in this case our SP. + 'assertionConsumerService' => array( + // URL Location where the from the IdP will be returned + 'url' => $url, + // SAML protocol binding to be used when returning the + // message. Onelogin Toolkit supports for this endpoint the + // HTTP-POST binding only + 'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + ), +// // If you need to specify requested attributes, set a +// // attributeConsumingService. nameFormat, attributeValue and +// // friendlyName can be omitted. Otherwise remove this section. +// "attributeConsumingService" => array( +// "serviceName" => "SP test", +// "serviceDescription" => "Test Service", +// "requestedAttributes" => array( +// array( +// "name" => "", +// "isRequired" => false, +// "nameFormat" => "", +// "friendlyName" => "", +// "attributeValue" => "" +// ) +// ) +// ), +// // Specifies info about where and how the message MUST be +// // returned to the requester, in this case our SP. +// 'singleLogoutService' => array( +// // URL Location where the from the IdP will be returned +// 'url' => '', +// // SAML protocol binding to be used when returning the +// // message. Onelogin Toolkit supports for this endpoint the +// // HTTP-Redirect binding only +// 'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', +// ), +// // Specifies constraints on the name identifier to be used to +// // represent the requested subject. +// // Take a look on lib/Saml2/Constants.php to see the NameIdFormat supported +// 'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified', +// +// // Usually x509cert and privateKey of the SP are provided by files placed at +// // the certs folder. But we can also provide them with the following parameters +// 'x509cert' => '', +// 'privateKey' => '', +// +// /* +// * Key rollover +// * If you plan to update the SP x509cert and privateKey +// * you can define here the new x509cert and it will be +// * published on the SP metadata so Identity Providers can +// * read them and get ready for rollover. +// */ +// // 'x509certNew' => '', + ], + 'idp' => [ + 'entityId' => $metadata['EntityDescriptor']['@entityID'], + 'singleSignOnService' => [ + 'url' => $metadata['EntityDescriptor']['IDPSSODescriptor']['SingleSignOnService'][0]['@Location'], + ], + 'x509cert' => $metadata['EntityDescriptor']['IDPSSODescriptor']['KeyDescriptor']['KeyInfo']['X509Data']['X509Certificate'], + ]]; + + try { + $auth = new Auth($samlsettings); + } catch (Exception $e) { + http_response_code(500); + print_r($e); + die('an error occured'); + } + + if (!empty($_POST['SAMLResponse']) && !empty($_POST['RelayState'])) { + $auth->processResponse(null); + + $errors = $auth->getErrors(); + if (empty($errors)) { + // user has authenticated successfully + $needsAuth = false; + $_SESSION['samlUserdata'] = $auth->getAttributes(); + $_SESSION['samlOK'] = true; + header('Location: ' . $_SESSION['return']); + unset($_SESSION['return']); + session_write_close(); + file_put_contents($logdir . 'ok.' . $t . '.log', print_r($_SESSION, true)); + file_put_contents($logdir . 'xml.' . $t . '.log', $auth->getLastResponseXML()); + } else { + file_put_contents($logdir . 'err.' . $t . '.log', print_r($errors, true) . "\n\n--\n\n" . print_r($auth->getLastErrorReason(), true) . "\n\n--\n\n" . print_r($auth->getLastErrorException(), true)); + } + } else { + $auth->login(); + } +} + + +function xmlToArray($xml, $options = array()) +{ + $defaults = array( + 'namespaceSeparator' => ':',//you may want this to be something other than a colon + 'attributePrefix' => '@', //to distinguish between attributes and nodes with the same name + 'alwaysArray' => array(), //array of xml tag names which should always become arrays + 'autoArray' => true, //only create arrays for tags which appear more than once + 'textContent' => '$', //key used for the text content of elements + 'autoText' => true, //skip textContent key if node has no attributes or child nodes + 'keySearch' => false, //optional search and replace on tag and attribute names + 'keyReplace' => false //replace values for above search values (as passed to str_replace()) + ); + $options = array_merge($defaults, $options); + $namespaces = $xml->getDocNamespaces(true); + $namespaces[''] = null; //add base (empty) namespace + + //get attributes from all namespaces + $attributesArray = array(); + foreach ($namespaces as $prefix => $namespace) { + foreach ($xml->attributes($namespace) as $attributeName => $attribute) { + //replace characters in attribute name + if ($options['keySearch']) $attributeName = + str_replace($options['keySearch'], $options['keyReplace'], $attributeName); + $attributeKey = $options['attributePrefix'] + . ($prefix ? $prefix . $options['namespaceSeparator'] : '') + . $attributeName; + $attributesArray[$attributeKey] = (string)$attribute; + } + } + + //get child nodes from all namespaces + $tagsArray = array(); + foreach ($namespaces as $prefix => $namespace) { + foreach ($xml->children($namespace) as $childXml) { + //recurse into child nodes + $childArray = xmlToArray($childXml, $options); + foreach ($childArray as $childTagName => $childProperties) { + break; + } + //list($childTagName, $childProperties) = each($childArray); + + //replace characters in tag name + if ($options['keySearch']) $childTagName = + str_replace($options['keySearch'], $options['keyReplace'], $childTagName); + //add namespace prefix, if any + if ($prefix) $childTagName = $prefix . $options['namespaceSeparator'] . $childTagName; + + if (!isset($tagsArray[$childTagName])) { + //only entry with this key + //test if tags of this type should always be arrays, no matter the element count + $tagsArray[$childTagName] = + in_array($childTagName, $options['alwaysArray']) || !$options['autoArray'] + ? array($childProperties) : $childProperties; + } elseif ( + is_array($tagsArray[$childTagName]) && array_keys($tagsArray[$childTagName]) + === range(0, count($tagsArray[$childTagName]) - 1) + ) { + //key already exists and is integer indexed array + $tagsArray[$childTagName][] = $childProperties; + } else { + //key exists so convert to integer indexed array with previous value in position 0 + $tagsArray[$childTagName] = array($tagsArray[$childTagName], $childProperties); + } + } + } + + //get text content of node + $textContentArray = array(); + $plainText = trim((string)$xml); + if ($plainText !== '') $textContentArray[$options['textContent']] = $plainText; + + //stick it all together + $propertiesArray = !$options['autoText'] || $attributesArray || $tagsArray || ($plainText === '') + ? array_merge($attributesArray, $tagsArray, $textContentArray) : $plainText; + + //return node as array + return array( + $xml->getName() => $propertiesArray + ); +} + +function getMetadata() +{ + global $metadata; + $limit = time() - 14400; + $cachefile = __DIR__ . '/_metadata'; + + if (!file_exists($cachefile) || filesize($cachefile) <= 20 || filemtime($cachefile) < $limit) { + $client = new Client(); + $response = $client->get($metadata, ['timeout' => 30]); + $c = $response->getBody()->getContents(); + + if (!$c) { + return json_decode(file_get_contents($cachefile), true); + } + + $xml = simplexml_load_string($c); + + $metadata = xmlToArray($xml); + file_put_contents($cachefile, json_encode($metadata)); + return $metadata; + } else { + return json_decode(file_get_contents($cachefile), true); + } + +} \ No newline at end of file diff --git a/VacheronSSO/composer.json b/VacheronSSO/composer.json index 277fb90..0878860 100644 --- a/VacheronSSO/composer.json +++ b/VacheronSSO/composer.json @@ -1,6 +1,6 @@ { "require": { - "php": ">=7.0", + "php": ">=8.0", "ext-json": "*", "ext-xml": "*", "guzzlehttp/guzzle": "^7.0", diff --git a/VacheronSSO/index.php b/VacheronSSO/index.php new file mode 100644 index 0000000..88d4134 --- /dev/null +++ b/VacheronSSO/index.php @@ -0,0 +1,7 @@ +