Skip to content

Commit 06bf35b

Browse files
committed
Provide better support to NameIdFormat
1 parent 7f053a5 commit 06bf35b

File tree

8 files changed

+119
-10
lines changed

8 files changed

+119
-10
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,7 @@ SAML 2 Authentication Response class
11311131
* `getNameIdData` - Gets the NameID Data provided by the SAML response from the
11321132
IdP.
11331133
* `getNameId` - Gets the NameID provided by the SAML response from the IdP.
1134+
* `getNameIdFormat` - Gets the NameID Format provided by the SAML response from the IdP.
11341135
* `getSessionNotOnOrAfter` - Gets the SessionNotOnOrAfter from the
11351136
AuthnStatement
11361137
* `getSessionIndex` - Gets the SessionIndex from the AuthnStatement.

demo1/index.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,19 @@
3131
$paramters = array();
3232
$nameId = null;
3333
$sessionIndex = null;
34+
$nameIdFormat = null;
35+
3436
if (isset($_SESSION['samlNameId'])) {
3537
$nameId = $_SESSION['samlNameId'];
3638
}
3739
if (isset($_SESSION['samlSessionIndex'])) {
3840
$sessionIndex = $_SESSION['samlSessionIndex'];
3941
}
42+
if (isset($_SESSION['samlNameIdFormat'])) {
43+
$nameIdFormat = $_SESSION['samlNameIdFormat'];
44+
}
4045

41-
$auth->logout($returnTo, $paramters, $nameId, $sessionIndex);
46+
$auth->logout($returnTo, $paramters, $nameId, $sessionIndex, false, $nameIdFormat);
4247

4348
# If LogoutRequest ID need to be saved in order to later validate it, do instead
4449
# $sloBuiltUrl = $auth->logout(null, $paramters, $nameId, $sessionIndex, true);
@@ -70,6 +75,7 @@
7075

7176
$_SESSION['samlUserdata'] = $auth->getAttributes();
7277
$_SESSION['samlNameId'] = $auth->getNameId();
78+
$_SESSION['samlNameIdFormat'] = $auth->getNameIdFormat();
7379
$_SESSION['samlSessionIndex'] = $auth->getSessionIndex();
7480
unset($_SESSION['AuthNRequestID']);
7581
if (isset($_POST['RelayState']) && OneLogin_Saml2_Utils::getSelfURL() != $_POST['RelayState']) {

lib/Saml2/Auth.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ class OneLogin_Saml2_Auth
2828
*/
2929
private $_nameid;
3030

31+
/**
32+
* NameID Format
33+
*
34+
* @var string
35+
*/
36+
private $_nameidFormat;
37+
3138
/**
3239
* If user is authenticated.
3340
*
@@ -126,6 +133,7 @@ public function processResponse($requestId = null)
126133
if ($response->isValid($requestId)) {
127134
$this->_attributes = $response->getAttributes();
128135
$this->_nameid = $response->getNameId();
136+
$this->_nameidFormat = $response->getNameIdFormat();
129137
$this->_authenticated = true;
130138
$this->_sessionIndex = $response->getSessionIndex();
131139
$this->_sessionExpiration = $response->getSessionNotOnOrAfter();
@@ -265,6 +273,16 @@ public function getNameId()
265273
return $this->_nameid;
266274
}
267275

276+
/**
277+
* Returns the nameID Format
278+
*
279+
* @return string The nameID Format of the assertion
280+
*/
281+
public function getNameIdFormat()
282+
{
283+
return $this->_nameidFormat;
284+
}
285+
268286
/**
269287
* Returns the SessionIndex
270288
*
@@ -369,12 +387,13 @@ public function login($returnTo = null, $parameters = array(), $forceAuthn = fal
369387
* @param string|null $nameId The NameID that will be set in the LogoutRequest.
370388
* @param string|null $sessionIndex The SessionIndex (taken from the SAML Response in the SSO process).
371389
* @param bool $stay True if we want to stay (returns the url string) False to redirect
390+
* @param string|null $nameIdFormat The NameID Format will be set in the LogoutRequest.
372391
*
373392
* @return If $stay is True, it return a string with the SLO URL + LogoutRequest + parameters
374393
*
375394
* @throws OneLogin_Saml2_Error
376395
*/
377-
public function logout($returnTo = null, $parameters = array(), $nameId = null, $sessionIndex = null, $stay=false)
396+
public function logout($returnTo = null, $parameters = array(), $nameId = null, $sessionIndex = null, $stay=false, $nameIdFormat = null)
378397
{
379398
assert('is_array($parameters)');
380399

@@ -390,7 +409,7 @@ public function logout($returnTo = null, $parameters = array(), $nameId = null,
390409
$nameId = $this->_nameid;
391410
}
392411

393-
$logoutRequest = new OneLogin_Saml2_LogoutRequest($this->_settings, null, $nameId, $sessionIndex);
412+
$logoutRequest = new OneLogin_Saml2_LogoutRequest($this->_settings, null, $nameId, $sessionIndex, $nameIdFormat);
394413

395414
$this->_lastRequestID = $logoutRequest->id;
396415

lib/Saml2/LogoutRequest.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,13 @@ class OneLogin_Saml2_LogoutRequest
3434
/**
3535
* Constructs the Logout Request object.
3636
*
37-
* @param OneLogin_Saml2_Settings $settings Settings
38-
* @param string|null $request A UUEncoded Logout Request.
39-
* @param string|null $nameId The NameID that will be set in the LogoutRequest.
40-
* @param string|null $sessionIndex The SessionIndex (taken from the SAML Response in the SSO process).
37+
* @param OneLogin_Saml2_Settings $settings Settings
38+
* @param string|null $request A UUEncoded Logout Request.
39+
* @param string|null $nameId The NameID that will be set in the LogoutRequest.
40+
* @param string|null $sessionIndex The SessionIndex (taken from the SAML Response in the SSO process).
41+
* @param string|null $nameIdFormat The NameID Format will be set in the LogoutRequest.
4142
*/
42-
public function __construct(OneLogin_Saml2_Settings $settings, $request = null, $nameId = null, $sessionIndex = null)
43+
public function __construct(OneLogin_Saml2_Settings $settings, $request = null, $nameId = null, $sessionIndex = null, $nameIdFormat = null)
4344
{
4445

4546
$this->_settings = $settings;
@@ -62,7 +63,9 @@ public function __construct(OneLogin_Saml2_Settings $settings, $request = null,
6263
}
6364

6465
if (!empty($nameId)) {
65-
$nameIdFormat = $spData['NameIDFormat'];
66+
if (empty($nameIdFormat)) {
67+
$nameIdFormat = $spData['NameIDFormat'];
68+
}
6669
$spNameQualifier = null;
6770
} else {
6871
$nameId = $idpData['entityId'];

lib/Saml2/Response.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,21 @@ public function getNameId()
479479
return $nameIdvalue;
480480
}
481481

482+
/**
483+
* Gets the NameID Format provided by the SAML response from the IdP.
484+
*
485+
* @return string Name ID Format
486+
*/
487+
public function getNameIdFormat()
488+
{
489+
$nameIdFormat = null;
490+
$nameIdData = $this->getNameIdData();
491+
if (!empty($nameIdData) && isset($nameIdData['Format'])) {
492+
$nameIdFormat = $nameIdData['Format'];
493+
}
494+
return $nameIdFormat;
495+
}
496+
482497
/**
483498
* Gets the SessionNotOnOrAfter from the AuthnStatement.
484499
* Could be used to set the local session expiration

tests/src/OneLogin/Saml2/AuthTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public function testProcessNoResponse()
9090
* @covers OneLogin_Saml2_Auth::getAttributes
9191
* @covers OneLogin_Saml2_Auth::getAttribute
9292
* @covers OneLogin_Saml2_Auth::getNameId
93+
* @covers OneLogin_Saml2_Auth::getNameIdFormat
9394
* @covers OneLogin_Saml2_Auth::getErrors
9495
* @covers OneLogin_Saml2_Auth::getSessionIndex
9596
* @covers OneLogin_Saml2_Auth::getSessionExpiration
@@ -105,6 +106,7 @@ public function testProcessResponseInvalid()
105106
$this->assertFalse($this->_auth->isAuthenticated());
106107
$this->assertEmpty($this->_auth->getAttributes());
107108
$this->assertNull($this->_auth->getNameId());
109+
$this->assertNull($this->_auth->getNameIdFormat());
108110
$this->assertNull($this->_auth->getSessionIndex());
109111
$this->assertNull($this->_auth->getSessionExpiration());
110112
$this->assertNull($this->_auth->getAttribute('uid'));
@@ -153,6 +155,7 @@ public function testProcessResponseInvalidRequestId()
153155
* @covers OneLogin_Saml2_Auth::getAttributes
154156
* @covers OneLogin_Saml2_Auth::getAttribute
155157
* @covers OneLogin_Saml2_Auth::getNameId
158+
* @covers OneLogin_Saml2_Auth::getNameIdFormat
156159
* @covers OneLogin_Saml2_Auth::getSessionIndex
157160
* @covers OneLogin_Saml2_Auth::getSessionExpiration
158161
* @covers OneLogin_Saml2_Auth::getErrors
@@ -165,6 +168,7 @@ public function testProcessResponseValid()
165168
$this->_auth->processResponse();
166169
$this->assertTrue($this->_auth->isAuthenticated());
167170
$this->assertEquals('492882615acf31c8096b627245d76ae53036c090', $this->_auth->getNameId());
171+
$this->assertEquals('urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', $this->_auth->getNameIdFormat());
168172
$attributes = $this->_auth->getAttributes();
169173
$this->assertNotEmpty($attributes);
170174
$this->assertEquals($this->_auth->getAttribute('mail'), $attributes['mail']);

tests/src/OneLogin/Saml2/LogoutRequestTest.php

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ public function testConstructorWithSessionIndex()
8686
$sessionIndex = '_51be37965feb5579d803141076936dc2e9d1d98ebf';
8787
$settings = new OneLogin_Saml2_Settings($settingsInfo);
8888

89-
9089
$logoutRequest = new OneLogin_Saml2_LogoutRequest($settings, null, null, $sessionIndex);
9190

9291
$parameters = array('SAMLRequest' => $logoutRequest->getRequest());
@@ -104,6 +103,39 @@ public function testConstructorWithSessionIndex()
104103
$this->assertEquals(array($sessionIndex), $sessionIndexes);
105104
}
106105

106+
/**
107+
* Tests the OneLogin_Saml2_LogoutRequest Constructor.
108+
*
109+
* @covers OneLogin_Saml2_LogoutRequest
110+
*/
111+
public function testConstructorWithNameIdFormat()
112+
{
113+
$settingsDir = TEST_ROOT .'/settings/';
114+
include $settingsDir.'settings1.php';
115+
116+
$nameId = '[email protected]';
117+
$nameIdFormat = 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient';
118+
$settings = new OneLogin_Saml2_Settings($settingsInfo);
119+
120+
$logoutRequest = new OneLogin_Saml2_LogoutRequest($settings, null, $nameId, null, $nameIdFormat);
121+
122+
$parameters = array('SAMLRequest' => $logoutRequest->getRequest());
123+
$logoutUrl = OneLogin_Saml2_Utils::redirect('http://idp.example.com/SingleLogoutService.php', $parameters, true);
124+
$this->assertRegExp('#^http://idp\.example\.com\/SingleLogoutService\.php\?SAMLRequest=#', $logoutUrl);
125+
parse_str(parse_url($logoutUrl, PHP_URL_QUERY), $exploded);
126+
// parse_url already urldecode de params so is not required.
127+
$payload = $exploded['SAMLRequest'];
128+
$decoded = base64_decode($payload);
129+
$inflated = gzinflate($decoded);
130+
$this->assertRegExp('#^<samlp:LogoutRequest#', $inflated);
131+
132+
$logoutNameId = OneLogin_Saml2_LogoutRequest::getNameId($inflated);
133+
$this->assertEquals($nameId, $logoutNameId);
134+
135+
$logoutNameIdData = OneLogin_Saml2_LogoutRequest::getNameIdData($inflated);
136+
$this->assertEquals($nameIdFormat, $logoutNameIdData['Format']);
137+
}
138+
107139
/**
108140
* Tests the OneLogin_Saml2_LogoutRequest Constructor.
109141
* The creation of a deflated SAML Logout Request

tests/src/OneLogin/Saml2/ResponseTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,35 @@ public function testReturnNameId()
134134
}
135135
}
136136

137+
/**
138+
* Tests the getNameIdFormat method of the OneLogin_Saml2_Response
139+
*
140+
* @covers OneLogin_Saml2_Response::getNameIdFormat
141+
*/
142+
public function testGetNameIdFormat()
143+
{
144+
$xml = file_get_contents(TEST_ROOT . '/data/responses/response1.xml.base64');
145+
$response = new OneLogin_Saml2_Response($this->_settings, $xml);
146+
$this->assertEquals('urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', $response->getNameIdFormat());
147+
148+
$xml2 = file_get_contents(TEST_ROOT . '/data/responses/response_encrypted_nameid.xml.base64');
149+
$response2 = new OneLogin_Saml2_Response($this->_settings, $xml2);
150+
$this->assertEquals('urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified', $response2->getNameIdFormat());
151+
152+
$xml3 = file_get_contents(TEST_ROOT . '/data/responses/valid_encrypted_assertion.xml.base64');
153+
$response3 = new OneLogin_Saml2_Response($this->_settings, $xml3);
154+
$this->assertEquals('urn:oasis:names:tc:SAML:2.0:nameid-format:transient', $response3->getNameIdFormat());
155+
156+
$xml4 = file_get_contents(TEST_ROOT . '/data/responses/invalids/no_nameid.xml.base64');
157+
$response4 = new OneLogin_Saml2_Response($this->_settings, $xml4);
158+
159+
try {
160+
$nameId4 = $response4->getNameIdFormat();
161+
} catch (Exception $e) {
162+
$this->assertContains('Not NameID found in the assertion of the Response', $e->getMessage());
163+
}
164+
}
165+
137166
/**
138167
* Tests the getNameIdData method of the OneLogin_Saml2_Response
139168
*

0 commit comments

Comments
 (0)