Skip to content

Commit 5c174df

Browse files
committed
Update php-saml to 2.11.0
1 parent 755eb19 commit 5c174df

10 files changed

Lines changed: 499 additions & 151 deletions

File tree

onelogin-saml-sso/php/lib/Saml2/Auth.php

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ class OneLogin_Saml2_Auth
3434
*/
3535
private $_nameidFormat;
3636

37+
38+
/**
39+
* NameID NameQualifier
40+
*
41+
* @var string
42+
*/
43+
private $_nameidNameQualifier;
44+
3745
/**
3846
* If user is authenticated.
3947
*
@@ -177,6 +185,7 @@ public function processResponse($requestId = null)
177185
$this->_attributes = $response->getAttributes();
178186
$this->_nameid = $response->getNameId();
179187
$this->_nameidFormat = $response->getNameIdFormat();
188+
$this->_nameidNameQualifier = $response->getNameIdNameQualifier();
180189
$this->_authenticated = true;
181190
$this->_sessionIndex = $response->getSessionIndex();
182191
$this->_sessionExpiration = $response->getSessionNotOnOrAfter();
@@ -336,6 +345,16 @@ public function getNameIdFormat()
336345
return $this->_nameidFormat;
337346
}
338347

348+
/**
349+
* Returns the nameID NameQualifier
350+
*
351+
* @return string The nameID NameQualifier of the assertion
352+
*/
353+
public function getNameIdNameQualifier()
354+
{
355+
return $this->_nameidNameQualifier;
356+
}
357+
339358
/**
340359
* Returns the SessionIndex
341360
*
@@ -436,18 +455,19 @@ public function login($returnTo = null, $parameters = array(), $forceAuthn = fal
436455
/**
437456
* Initiates the SLO process.
438457
*
439-
* @param string|null $returnTo The target URL the user should be returned to after logout.
440-
* @param array $parameters Extra parameters to be added to the GET
441-
* @param string|null $nameId The NameID that will be set in the LogoutRequest.
442-
* @param string|null $sessionIndex The SessionIndex (taken from the SAML Response in the SSO process).
443-
* @param bool $stay True if we want to stay (returns the url string) False to redirect
444-
* @param string|null $nameIdFormat The NameID Format will be set in the LogoutRequest.
458+
* @param string|null $returnTo The target URL the user should be returned to after logout.
459+
* @param array $parameters Extra parameters to be added to the GET
460+
* @param string|null $nameId The NameID that will be set in the LogoutRequest.
461+
* @param string|null $sessionIndex The SessionIndex (taken from the SAML Response in the SSO process).
462+
* @param bool $stay True if we want to stay (returns the url string) False to redirect
463+
* @param string|null $nameIdFormat The NameID Format will be set in the LogoutRequest.
464+
* @param string|null $nameIdNameQualifier The NameID NameQualifier will be set in the LogoutRequest.
445465
*
446466
* @return If $stay is True, it return a string with the SLO URL + LogoutRequest + parameters
447467
*
448468
* @throws OneLogin_Saml2_Error
449469
*/
450-
public function logout($returnTo = null, $parameters = array(), $nameId = null, $sessionIndex = null, $stay = false, $nameIdFormat = null)
470+
public function logout($returnTo = null, $parameters = array(), $nameId = null, $sessionIndex = null, $stay = false, $nameIdFormat = null, $nameIdNameQualifier = null)
451471
{
452472
assert('is_array($parameters)');
453473

@@ -466,7 +486,7 @@ public function logout($returnTo = null, $parameters = array(), $nameId = null,
466486
$nameIdFormat = $this->_nameidFormat;
467487
}
468488

469-
$logoutRequest = new OneLogin_Saml2_LogoutRequest($this->_settings, null, $nameId, $sessionIndex, $nameIdFormat);
489+
$logoutRequest = new OneLogin_Saml2_LogoutRequest($this->_settings, null, $nameId, $sessionIndex, $nameIdFormat, $nameIdNameQualifier);
470490

471491
$this->_lastRequest = $logoutRequest->getXML();
472492
$this->_lastRequestID = $logoutRequest->id;

onelogin-saml-sso/php/lib/Saml2/AuthnRequest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ public function __construct(OneLogin_Saml2_Settings $settings, $forceAuthn = fal
114114
}
115115
}
116116

117+
$spEntityId = htmlspecialchars($spData['entityId'], ENT_QUOTES);
118+
$acsUrl = htmlspecialchars($spData['assertionConsumerService']['url'], ENT_QUOTES);
117119
$request = <<<AUTHNREQUEST
118120
<samlp:AuthnRequest
119121
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
@@ -124,8 +126,8 @@ public function __construct(OneLogin_Saml2_Settings $settings, $forceAuthn = fal
124126
IssueInstant="$issueInstant"
125127
Destination="{$idpData['singleSignOnService']['url']}"
126128
ProtocolBinding="{$spData['assertionConsumerService']['binding']}"
127-
AssertionConsumerServiceURL="{$spData['assertionConsumerService']['url']}">
128-
<saml:Issuer>{$spData['entityId']}</saml:Issuer>
129+
AssertionConsumerServiceURL="{$acsUrl}">
130+
<saml:Issuer>{$spEntityId}</saml:Issuer>
129131
{$nameIdPolicyStr}
130132
{$requestedAuthnStr}
131133
</samlp:AuthnRequest>
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
<?php
2+
3+
/**
4+
* IdP Metadata Parser of OneLogin PHP Toolkit
5+
*
6+
*/
7+
8+
class OneLogin_Saml2_IdPMetadataParser
9+
{
10+
/**
11+
* Get IdP Metadata Info from URL
12+
*
13+
* @param string $url URL where the IdP metadata is published
14+
* @param string $entityId Entity Id of the desired IdP, if no
15+
* entity Id is provided and the XML
16+
* metadata contains more than one
17+
* IDPSSODescriptor, the first is returned
18+
* @param string $desiredNameIdFormat If available on IdP metadata, use that nameIdFormat
19+
*
20+
* @return array metadata info in php-saml settings format
21+
*/
22+
public static function parseRemoteXML($url, $entityId = null, $desiredNameIdFormat = null)
23+
{
24+
$metadataInfo = array();
25+
26+
try {
27+
$ch = curl_init($url);
28+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
29+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
30+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
31+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
32+
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
33+
34+
$xml = curl_exec($ch);
35+
if ($xml !== false) {
36+
$metadataInfo = self::parseXML($xml, $entityId);
37+
} else {
38+
throw new Exception(curl_error($ch), curl_errno($ch));
39+
}
40+
} catch (Exception $e) {
41+
}
42+
return $metadataInfo;
43+
}
44+
45+
/**
46+
* Get IdP Metadata Info from File
47+
*
48+
* @param string $filepath File path
49+
* @param string $entityId Entity Id of the desired IdP, if no
50+
* entity Id is provided and the XML
51+
* metadata contains more than one
52+
* IDPSSODescriptor, the first is returned
53+
* @param string $desiredNameIdFormat If available on IdP metadata, use that nameIdFormat
54+
*
55+
* @return array metadata info in php-saml settings format
56+
*/
57+
public static function parseFileXML($filepath, $entityId = null, $desiredNameIdFormat = null)
58+
{
59+
$metadataInfo = array();
60+
61+
try {
62+
if (file_exists($filepath)) {
63+
$data = file_get_contents($filepath);
64+
$metadataInfo = self::parseXML($data, $entityId);
65+
}
66+
} catch (Exception $e) {
67+
}
68+
return $metadataInfo;
69+
}
70+
71+
/**
72+
* Get IdP Metadata Info from URL
73+
*
74+
* @param string $xml XML that contains IdP metadata
75+
* @param string $entityId Entity Id of the desired IdP, if no
76+
* entity Id is provided and the XML
77+
* metadata contains more than one
78+
* IDPSSODescriptor, the first is returned
79+
* @param string $desiredNameIdFormat If available on IdP metadata, use that nameIdFormat
80+
*
81+
* @return array metadata info in php-saml settings format
82+
*/
83+
public static function parseXML($xml, $entityId = null, $desiredNameIdFormat = null)
84+
{
85+
$metadataInfo = array();
86+
87+
$dom = new DOMDocument();
88+
$dom->preserveWhiteSpace = false;
89+
$dom->formatOutput = true;
90+
try {
91+
$dom = OneLogin_Saml2_Utils::loadXML($dom, $xml);
92+
if (!$dom) {
93+
throw new Exception('Error parsing metadata');
94+
}
95+
96+
$customIdPStr = '';
97+
if (!empty($entityId)) {
98+
$customIdPStr = '[@entityID="' . $entityId . '"]';
99+
}
100+
$idpDescryptorXPath = '//md:EntityDescriptor' . $customIdPStr . '/md:IDPSSODescriptor';
101+
102+
$idpDescriptorNodes = OneLogin_Saml2_Utils::query($dom, $idpDescryptorXPath);
103+
104+
if (isset($idpDescriptorNodes) && $idpDescriptorNodes->length > 0) {
105+
$metadataInfo['idp'] = array();
106+
107+
$idpDescriptor = $idpDescriptorNodes->item(0);
108+
109+
if (empty($entityId) && $idpDescriptor->parentNode->hasAttribute('entityID')) {
110+
$entityId = $idpDescriptor->parentNode->getAttribute('entityID');
111+
}
112+
113+
if (!empty($entityId)) {
114+
$metadataInfo['idp']['entityId'] = $entityId;
115+
}
116+
117+
$ssoNodes = OneLogin_Saml2_Utils::query($dom, './md:SingleSignOnService[@Binding="'.OneLogin_Saml2_Constants::BINDING_HTTP_REDIRECT.'"]', $idpDescriptor);
118+
if ($ssoNodes->length < 1) {
119+
$ssoNodes = OneLogin_Saml2_Utils::query($dom, './md:SingleSignOnService', $idpDescriptor);
120+
}
121+
if ($ssoNodes->length > 0) {
122+
$metadataInfo['idp']['singleSignOnService'] = array(
123+
'url' => $ssoNodes->item(0)->getAttribute('Location'),
124+
'binding' => $ssoNodes->item(0)->getAttribute('Binding')
125+
);
126+
}
127+
128+
$sloNodes = OneLogin_Saml2_Utils::query($dom, './md:SingleLogoutService[@Binding="'.OneLogin_Saml2_Constants::BINDING_HTTP_REDIRECT.'"]', $idpDescriptor);
129+
if ($sloNodes->length < 1) {
130+
$sloNodes = OneLogin_Saml2_Utils::query($dom, './md:SingleLogoutService', $idpDescriptor);
131+
}
132+
if ($sloNodes->length > 0) {
133+
$metadataInfo['idp']['singleLogoutService'] = array(
134+
'url' => $sloNodes->item(0)->getAttribute('Location'),
135+
'binding' => $sloNodes->item(0)->getAttribute('Binding')
136+
);
137+
}
138+
139+
$keyDescriptorCertSigningNodes = OneLogin_Saml2_Utils::query($dom, './md:KeyDescriptor[not(contains(@use, "encryption"))]/ds:KeyInfo/ds:X509Data/ds:X509Certificate', $idpDescriptor);
140+
141+
$keyDescriptorCertEncryptionNodes = OneLogin_Saml2_Utils::query($dom, './md:KeyDescriptor[not(contains(@use, "signing"))]/ds:KeyInfo/ds:X509Data/ds:X509Certificate', $idpDescriptor);
142+
143+
if (!empty($keyDescriptorCertSigningNodes) || !empty($keyDescriptorCertEncryptionNodes)) {
144+
$metadataInfo['idp']['x509certMulti'] = array();
145+
if (!empty($keyDescriptorCertSigningNodes)) {
146+
$idpInfo['x509certMulti']['signing'] = array();
147+
foreach ($keyDescriptorCertSigningNodes as $keyDescriptorCertSigningNode) {
148+
$metadataInfo['idp']['x509certMulti']['signing'][] = OneLogin_Saml2_Utils::formatCert($keyDescriptorCertSigningNode->nodeValue, false);
149+
}
150+
}
151+
if (!empty($keyDescriptorCertEncryptionNodes)) {
152+
$idpInfo['x509certMulti']['encryption'] = array();
153+
foreach ($keyDescriptorCertEncryptionNodes as $keyDescriptorCertEncryptionNode) {
154+
$metadataInfo['idp']['x509certMulti']['encryption'][] = OneLogin_Saml2_Utils::formatCert($keyDescriptorCertEncryptionNode->nodeValue, false);
155+
}
156+
}
157+
158+
$idpCertdata = $metadataInfo['idp']['x509certMulti'];
159+
if (count($idpCertdata) == 1 || ((isset($idpCertdata['signing']) && count($idpCertdata['signing']) == 1) && isset($idpCertdata['encryption']) && count($idpCertdata['encryption']) == 1 && strcmp($idpCertdata['signing'][0], $idpCertdata['encryption'][0]) == 0)) {
160+
if (isset($metadataInfo['idp']['x509certMulti']['signing'][0])) {
161+
$metadataInfo['idp']['x509cert'] = $metadataInfo['idp']['x509certMulti']['signing'][0];
162+
} else {
163+
$metadataInfo['idp']['x509cert'] = $metadataInfo['idp']['x509certMulti']['encryption'][0];
164+
}
165+
unset($metadataInfo['idp']['x509certMulti']);
166+
}
167+
}
168+
169+
$nameIdFormatNodes = OneLogin_Saml2_Utils::query($dom, './md:NameIDFormat', $idpDescriptor);
170+
if ($nameIdFormatNodes->length > 0) {
171+
$metadataInfo['sp']['NameIDFormat'] = $nameIdFormatNodes->item(0)->nodeValue;
172+
if (!empty($desiredNameIdFormat)) {
173+
foreach ($nameIdFormatNodes as $nameIdFormatNode) {
174+
if (strcmp($nameIdFormatNode->nodeValue, $desiredNameIdFormat) == 0) {
175+
$metadataInfo['sp']['NameIDFormat'] = $nameIdFormatNode->nodeValue;
176+
break;
177+
}
178+
}
179+
}
180+
}
181+
}
182+
} catch (Exception $e) {
183+
throw new Exception('Error parsing metadata. '.$e->getMessage());
184+
}
185+
186+
return $metadataInfo;
187+
}
188+
189+
/**
190+
* Inject metadata info into php-saml settings array
191+
*
192+
* @param string $settings php-saml settings array
193+
* @param string $metadataInfo array metadata info
194+
*
195+
* @return array settings
196+
*/
197+
public static function injectIntoSettings($settings, $metadataInfo)
198+
{
199+
if (isset($metadataInfo['idp']) && isset($settings['idp'])) {
200+
if (isset($metadataInfo['idp']['x509certMulti']) && !empty($metadataInfo['idp']['x509certMulti']) && isset($settings['idp']['x509cert'])) {
201+
unset($settings['idp']['x509cert']);
202+
}
203+
204+
if (isset($metadataInfo['idp']['x509cert']) && !empty($metadataInfo['idp']['x509cert']) && isset($settings['idp']['x509certMulti'])) {
205+
unset($settings['idp']['x509certMulti']);
206+
}
207+
}
208+
209+
return array_replace_recursive($settings, $metadataInfo);
210+
}
211+
}

0 commit comments

Comments
 (0)