Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions demo-django/saml/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"url": "https://<sp_domain>/?sls",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"NameIDFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified",
"NameIDFormats": ["urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified"],
"x509cert": "",
"privateKey": ""
},
Expand All @@ -25,6 +25,8 @@
"url": "https://app.onelogin.com/trust/saml2/http-redirect/slo/<onelogin_connector_id>",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"NameIDPolicyFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified",
"NameIDPolicyAllowCreate": true,
"x509cert": "<onelogin_connector_cert>"
}
}
}
4 changes: 3 additions & 1 deletion demo-flask/saml/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"url": "https://<sp_domain>/?sls",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"NameIDFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified",
"NameIDFormats": ["urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified"],
"x509cert": "",
"privateKey": ""
},
Expand All @@ -25,6 +25,8 @@
"url": "https://app.onelogin.com/trust/saml2/http-redirect/slo/<onelogin_connector_id>",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"NameIDPolicyFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified",
"NameIDPolicyAllowCreate": true,
"x509cert": "<onelogin_connector_cert>"
}
}
18 changes: 13 additions & 5 deletions src/onelogin/saml2/authn_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,19 @@ def __init__(self, settings, force_authn=False, is_passive=False):

destination = idp_data['singleSignOnService']['url']

name_id_policy_format = sp_data['NameIDFormat']
# NameIDPolicy element:
name_id_policy_str = ''
name_id_policy_attrs = ''
if 'wantNameIdEncrypted' in security and security['wantNameIdEncrypted']:
name_id_policy_format = OneLogin_Saml2_Constants.NAMEID_ENCRYPTED
else:
name_id_policy_format = idp_data.get('NameIDPolicyFormat')
if name_id_policy_format:
name_id_policy_attrs += 'Format="%s" ' % name_id_policy_format
if idp_data['NameIDPolicyAllowCreate']:
name_id_policy_attrs += 'AllowCreate="true" '
if name_id_policy_attrs:
name_id_policy_str = '<samlp:NameIDPolicy %s/>' % name_id_policy_attrs

provider_name_str = ''
organization_data = settings.get_organization()
Expand Down Expand Up @@ -97,9 +107,7 @@ def __init__(self, settings, force_authn=False, is_passive=False):
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
AssertionConsumerServiceURL="%(assertion_url)s">
<saml:Issuer>%(entity_id)s</saml:Issuer>
<samlp:NameIDPolicy
Format="%(name_id_policy)s"
AllowCreate="true" />
%(name_id_policy)s
%(requested_authn_context_str)s
</samlp:AuthnRequest>""" % \
{
Expand All @@ -111,7 +119,7 @@ def __init__(self, settings, force_authn=False, is_passive=False):
'destination': destination,
'assertion_url': sp_data['assertionConsumerService']['url'],
'entity_id': sp_data['entityId'],
'name_id_policy': name_id_policy_format,
'name_id_policy': name_id_policy_str,
'requested_authn_context_str': requested_authn_context_str,
}

Expand Down
2 changes: 1 addition & 1 deletion src/onelogin/saml2/logout_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def __init__(self, settings, request=None, name_id=None, session_index=None):
cert = idp_data['x509cert']

if name_id is not None:
nameIdFormat = sp_data['NameIDFormat']
nameIdFormat = idp_data['NameIDPolicyFormat']
else:
name_id = idp_data['entityId']
nameIdFormat = OneLogin_Saml2_Constants.NAMEID_ENTITY
Expand Down
9 changes: 7 additions & 2 deletions src/onelogin/saml2/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,18 @@ def builder(sp, authnsign=False, wsign=False, valid_until=None, cache_duration=N
contacts_info.append(contact)
str_contacts = '\n'.join(contacts_info)

str_nameid_formats = ''
for name_id_format in sp['NameIDFormats']:
str_nameid_formats += ' <md:NameIDFormat>%s</md:NameIDFormat>\n' % name_id_format

metadata = """<?xml version="1.0"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
validUntil="%(valid)s"
cacheDuration="%(cache)s"
entityID="%(entity_id)s">
<md:SPSSODescriptor AuthnRequestsSigned="%(authnsign)s" WantAssertionsSigned="%(wsign)s" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
%(sls)s <md:NameIDFormat>%(name_id_format)s</md:NameIDFormat>
%(sls)s
%(str_nameid_formats)s
<md:AssertionConsumerService Binding="%(binding)s"
Location="%(location)s"
index="1" />
Expand All @@ -139,7 +144,7 @@ def builder(sp, authnsign=False, wsign=False, valid_until=None, cache_duration=N
'entity_id': sp['entityId'],
'authnsign': str_authnsign,
'wsign': str_wsign,
'name_id_format': sp['NameIDFormat'],
'str_nameid_formats': str_nameid_formats,
'binding': sp['assertionConsumerService']['binding'],
'location': sp['assertionConsumerService']['url'],
'sls': sls,
Expand Down
2 changes: 1 addition & 1 deletion src/onelogin/saml2/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ def get_nameid_data(self):
if nameid_nodes:
nameid = nameid_nodes[0]
if nameid is None:
raise Exception('Not NameID found in the assertion of the Response')
return {'Value': None}

nameid_data = {'Value': nameid.text}
for attr in ['Format', 'SPNameQualifier', 'NameQualifier']:
Expand Down
15 changes: 13 additions & 2 deletions src/onelogin/saml2/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,19 @@ def __add_default_values(self):
self.__sp['singleLogoutService']['binding'] = OneLogin_Saml2_Constants.BINDING_HTTP_REDIRECT

# Related to nameID
if 'NameIDFormat' not in self.__sp:
self.__sp['NameIDFormat'] = OneLogin_Saml2_Constants.NAMEID_PERSISTENT
if 'NameIDFormats' not in self.__sp:
# Check if the older config setting, single NameIDFormat is present:
if 'NameIDFormat' in self.__sp:
self.__sp['NameIDFormats'] = [self.__sp['NameIDFormat']]
else:
self.__sp['NameIDFormats'] = [OneLogin_Saml2_Constants.NAMEID_PERSISTENT]
if 'NameIDPolicyFormat' not in self.__idp:
# Check for the old-style setting 'NameIDFormat' which set both NameIDFormats and NameIDPolicyFormat:
if 'NameIDFormat' in self.__sp:
self.__idp['NameIDPolicyFormat'] = self.__sp.pop('NameIDFormat')
self.__idp['NameIDPolicyAllowCreate'] = True
if 'NameIDPolicyAllowCreate' not in self.__idp:
self.__idp['NameIDPolicyAllowCreate'] = False # False is the default according to the spec
if 'nameIdEncrypted' not in self.__security:
self.__security['nameIdEncrypted'] = False

Expand Down
4 changes: 3 additions & 1 deletion tests/settings/settings1.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"singleLogoutService": {
"url": "http://stuff.com/endpoints/endpoints/sls.php"
},
"NameIDFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified"
"NameIDFormats": ["urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified"]
},
"idp": {
"entityId": "http://idp.example.com/",
Expand All @@ -20,6 +20,8 @@
"singleLogoutService": {
"url": "http://idp.example.com/SingleLogoutService.php"
},
"NameIDPolicyFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified",
"NameIDPolicyAllowCreate": true,
"x509cert": "MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo"
},
"security": {
Expand Down
13 changes: 3 additions & 10 deletions tests/src/OneLogin/saml2_tests/response_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,7 @@ def testReturnNameId(self):

xml_4 = self.file_contents(join(self.data_path, 'responses', 'invalids', 'no_nameid.xml.base64'))
response_4 = OneLogin_Saml2_Response(settings, xml_4)
try:
response_4.get_nameid()
self.assertTrue(False)
except Exception as e:
self.assertIn('Not NameID found in the assertion of the Response', e.message)
self.assertIsNone(response_4.get_nameid())

def testGetNameIdData(self):
"""
Expand Down Expand Up @@ -116,11 +112,8 @@ def testGetNameIdData(self):

xml_4 = self.file_contents(join(self.data_path, 'responses', 'invalids', 'no_nameid.xml.base64'))
response_4 = OneLogin_Saml2_Response(settings, xml_4)
try:
response_4.get_nameid_data()
self.assertTrue(False)
except Exception as e:
self.assertIn('Not NameID found in the assertion of the Response', e.message)
data = response_4.get_nameid_data()
self.assertEqual(data, {'Value': None})

def testCheckStatus(self):
"""
Expand Down
12 changes: 9 additions & 3 deletions tests/src/OneLogin/saml2_tests/settings_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ def testLoadSettingsFromDict(self):
settings = OneLogin_Saml2_Settings(settings_info)
self.assertEqual(len(settings.get_errors()), 0)

del settings_info['sp']['NameIDFormat']
del settings_info['sp']['NameIDFormats']
del settings_info['idp']['NameIDPolicyFormat']
del settings_info['idp']['NameIDPolicyAllowCreate']
del settings_info['idp']['x509cert']
settings_info['idp']['certFingerprint'] = 'afe71c28ef740bc87425be13a2263d37971daA1f9'
settings = OneLogin_Saml2_Settings(settings_info)
Expand Down Expand Up @@ -507,11 +509,15 @@ def testGetIdPData(self):
self.assertIn('entityId', idp_data)
self.assertIn('singleSignOnService', idp_data)
self.assertIn('singleLogoutService', idp_data)
self.assertIn('NameIDPolicyFormat', idp_data)
self.assertIn('NameIDPolicyAllowCreate', idp_data)
self.assertIn('x509cert', idp_data)

self.assertEqual('http://idp.example.com/', idp_data['entityId'])
self.assertEqual('http://idp.example.com/SSOService.php', idp_data['singleSignOnService']['url'])
self.assertEqual('http://idp.example.com/SingleLogoutService.php', idp_data['singleLogoutService']['url'])
self.assertEqual('urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified', idp_data['NameIDPolicyFormat'])
self.assertTrue(idp_data['NameIDPolicyAllowCreate'])

x509cert = 'MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo'
formated_x509_cert = OneLogin_Saml2_Utils.format_cert(x509cert)
Expand All @@ -528,12 +534,12 @@ def testGetSPData(self):
self.assertIn('entityId', sp_data)
self.assertIn('assertionConsumerService', sp_data)
self.assertIn('singleLogoutService', sp_data)
self.assertIn('NameIDFormat', sp_data)
self.assertIn('NameIDFormats', sp_data)

self.assertEqual('http://stuff.com/endpoints/metadata.php', sp_data['entityId'])
self.assertEqual('http://stuff.com/endpoints/endpoints/acs.php', sp_data['assertionConsumerService']['url'])
self.assertEqual('http://stuff.com/endpoints/endpoints/sls.php', sp_data['singleLogoutService']['url'])
self.assertEqual('urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified', sp_data['NameIDFormat'])
self.assertEqual(['urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified'], sp_data['NameIDFormats'])

def testGetSecurityData(self):
"""
Expand Down