Skip to content

Commit 265d019

Browse files
committed
Fix issue with LogoutRequest rejected by ADFS due NameID with unspecified format instead no format attribute
1 parent b089e78 commit 265d019

File tree

4 files changed

+66
-19
lines changed

4 files changed

+66
-19
lines changed

src/onelogin/saml2/logout_request.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,13 @@ def __init__(self, settings, request=None, name_id=None, session_index=None, nq=
7676
cert = idp_data['x509cert']
7777

7878
if name_id is not None:
79-
if name_id_format is not None:
80-
nameIdFormat = name_id_format
81-
else:
82-
nameIdFormat = sp_data['NameIDFormat']
79+
if not name_id_format and sp_data['NameIDFormat'] != OneLogin_Saml2_Constants.NAMEID_UNSPECIFIED:
80+
name_id_format = sp_data['NameIDFormat']
8381
else:
84-
nameIdFormat = OneLogin_Saml2_Constants.NAMEID_ENTITY
82+
name_id_format = OneLogin_Saml2_Constants.NAMEID_ENTITY
8583

8684
spNameQualifier = None
87-
if nameIdFormat == OneLogin_Saml2_Constants.NAMEID_ENTITY:
85+
if name_id_format == OneLogin_Saml2_Constants.NAMEID_ENTITY:
8886
name_id = idp_data['entityId']
8987
nq = None
9088
elif nq is not None:
@@ -94,7 +92,7 @@ def __init__(self, settings, request=None, name_id=None, session_index=None, nq=
9492
name_id_obj = OneLogin_Saml2_Utils.generate_name_id(
9593
name_id,
9694
spNameQualifier,
97-
nameIdFormat,
95+
name_id_format,
9896
cert,
9997
False,
10098
nq

src/onelogin/saml2/utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ def format_finger_print(fingerprint):
612612
return formated_fingerprint.lower()
613613

614614
@staticmethod
615-
def generate_name_id(value, sp_nq, sp_format, cert=None, debug=False, nq=None):
615+
def generate_name_id(value, sp_nq, sp_format=None, cert=None, debug=False, nq=None):
616616
"""
617617
Generates a nameID.
618618
@@ -646,7 +646,8 @@ def generate_name_id(value, sp_nq, sp_format, cert=None, debug=False, nq=None):
646646
name_id.setAttribute('SPNameQualifier', sp_nq)
647647
if nq is not None:
648648
name_id.setAttribute('NameQualifier', nq)
649-
name_id.setAttribute('Format', sp_format)
649+
if sp_format is not None:
650+
name_id.setAttribute('Format', sp_format)
650651
name_id.appendChild(doc.createTextNode(value))
651652
name_id_container.appendChild(name_id)
652653

tests/src/OneLogin/saml2_tests/logout_request_test.py

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,12 @@ def testConstructor(self):
5555
inflated = OneLogin_Saml2_Utils.decode_base64_and_inflate(payload)
5656
self.assertRegexpMatches(inflated, '^<samlp:LogoutRequest')
5757

58-
def testConstructorEncryptIdUsingX509certMulti(self):
58+
def testCreateDeflatedSAMLLogoutRequestURLParameter(self):
5959
"""
6060
Tests the OneLogin_Saml2_LogoutRequest Constructor.
61-
Case: Able to generate encryptedID with MultiCert
61+
The creation of a deflated SAML Logout Request
6262
"""
63-
settings_info = self.loadSettingsJSON('settings8.json')
64-
settings_info['security']['nameIdEncrypted'] = True
65-
settings = OneLogin_Saml2_Settings(settings_info)
66-
63+
settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
6764
logout_request = OneLogin_Saml2_Logout_Request(settings)
6865

6966
parameters = {'SAMLRequest': logout_request.get_request()}
@@ -74,14 +71,53 @@ def testConstructorEncryptIdUsingX509certMulti(self):
7471
payload = exploded['SAMLRequest'][0]
7572
inflated = OneLogin_Saml2_Utils.decode_base64_and_inflate(payload)
7673
self.assertRegexpMatches(inflated, '^<samlp:LogoutRequest')
77-
self.assertRegexpMatches(inflated, '<saml:EncryptedID>')
7874

79-
def testCreateDeflatedSAMLLogoutRequestURLParameter(self):
75+
def testConstructorWithNameIdFormatOnSettings(self):
8076
"""
8177
Tests the OneLogin_Saml2_LogoutRequest Constructor.
82-
The creation of a deflated SAML Logout Request
78+
Case: Defines NameIDFormat from settings
8379
"""
84-
settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
80+
settings_info = self.loadSettingsJSON()
81+
name_id = 'ONELOGIN_1e442c129e1f822c8096086a1103c5ee2c7cae1c'
82+
name_id_format = 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
83+
settings_info['sp']['NameIDFormat'] = name_id_format
84+
settings = OneLogin_Saml2_Settings(settings_info)
85+
logout_request = OneLogin_Saml2_Logout_Request(settings, name_id=name_id)
86+
logout_request_xml = OneLogin_Saml2_Utils.decode_base64_and_inflate(logout_request.get_request())
87+
name_id_data = OneLogin_Saml2_Logout_Request.get_nameid_data(logout_request_xml)
88+
expected_name_id_data = {
89+
'Value': name_id,
90+
'Format': name_id_format
91+
}
92+
self.assertEqual(expected_name_id_data, name_id_data)
93+
94+
def testConstructorWithoutNameIdFormat(self):
95+
"""
96+
Tests the OneLogin_Saml2_LogoutRequest Constructor.
97+
Case: Checks that NameIDFormat is not added
98+
"""
99+
settings_info = self.loadSettingsJSON()
100+
name_id = 'ONELOGIN_1e442c129e1f822c8096086a1103c5ee2c7cae1c'
101+
name_id_format = 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified'
102+
settings_info['sp']['NameIDFormat'] = name_id_format
103+
settings = OneLogin_Saml2_Settings(settings_info)
104+
logout_request = OneLogin_Saml2_Logout_Request(settings, name_id=name_id)
105+
logout_request_xml = OneLogin_Saml2_Utils.decode_base64_and_inflate(logout_request.get_request())
106+
name_id_data = OneLogin_Saml2_Logout_Request.get_nameid_data(logout_request_xml)
107+
expected_name_id_data = {
108+
'Value': name_id
109+
}
110+
self.assertEqual(expected_name_id_data, name_id_data)
111+
112+
def testConstructorEncryptIdUsingX509certMulti(self):
113+
"""
114+
Tests the OneLogin_Saml2_LogoutRequest Constructor.
115+
Case: Able to generate encryptedID with MultiCert
116+
"""
117+
settings_info = self.loadSettingsJSON('settings8.json')
118+
settings_info['security']['nameIdEncrypted'] = True
119+
settings = OneLogin_Saml2_Settings(settings_info)
120+
85121
logout_request = OneLogin_Saml2_Logout_Request(settings)
86122

87123
parameters = {'SAMLRequest': logout_request.get_request()}
@@ -92,6 +128,7 @@ def testCreateDeflatedSAMLLogoutRequestURLParameter(self):
92128
payload = exploded['SAMLRequest'][0]
93129
inflated = OneLogin_Saml2_Utils.decode_base64_and_inflate(payload)
94130
self.assertRegexpMatches(inflated, '^<samlp:LogoutRequest')
131+
self.assertRegexpMatches(inflated, '<saml:EncryptedID>')
95132

96133
def testGetIDFromSAMLLogoutRequest(self):
97134
"""

tests/src/OneLogin/saml2_tests/utils_test.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,17 @@ def testGenerateNameIdWithSPNameQualifier(self):
607607
expected_name_id_enc = '<saml:EncryptedID><xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/><dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><xenc:EncryptedKey><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/><xenc:CipherData><xenc:CipherValue>'
608608
self.assertIn(expected_name_id_enc, name_id_enc)
609609

610+
def testGenerateNameIdWithoutFormat(self):
611+
"""
612+
Tests the generateNameId method of the OneLogin_Saml2_Utils
613+
"""
614+
name_id_value = 'ONELOGIN_ce998811003f4e60f8b07a311dc641621379cfde'
615+
name_id_format = None
616+
617+
name_id = OneLogin_Saml2_Utils.generate_name_id(name_id_value, None, name_id_format)
618+
expected_name_id = '<saml:NameID>ONELOGIN_ce998811003f4e60f8b07a311dc641621379cfde</saml:NameID>'
619+
self.assertEqual(name_id, expected_name_id)
620+
610621
def testGenerateNameIdWithoutSPNameQualifier(self):
611622
"""
612623
Tests the generateNameId method of the OneLogin_Saml2_Utils

0 commit comments

Comments
 (0)