Skip to content

Commit

Permalink
Fix #184. Be able to provide a NameIDFormat to LogoutRequest
Browse files Browse the repository at this point in the history
  • Loading branch information
pitbulk committed Mar 11, 2017
1 parent a5423c3 commit 52e95da
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 3 deletions.
11 changes: 11 additions & 0 deletions src/onelogin/saml2/auth.py
Expand Up @@ -52,6 +52,7 @@ def __init__(self, request_data, old_settings=None, custom_base_path=None):
self.__settings = OneLogin_Saml2_Settings(old_settings, custom_base_path)
self.__attributes = []
self.__nameid = None
self.__nameid_format = None
self.__session_index = None
self.__session_expiration = None
self.__authenticated = False
Expand Down Expand Up @@ -97,6 +98,7 @@ def process_response(self, request_id=None):
if response.is_valid(self.__request_data, request_id):
self.__attributes = response.get_attributes()
self.__nameid = response.get_nameid()
self.__nameid_format = response.get_nameid_format()
self.__session_index = response.get_session_index()
self.__session_expiration = response.get_session_not_on_or_after()
self.__authenticated = True
Expand Down Expand Up @@ -214,6 +216,15 @@ def get_nameid(self):
"""
return self.__nameid

def get_nameid_format(self):
"""
Returns the nameID Format.
:returns: NameID Format
:rtype: string|None
"""
return self.__nameid_format

def get_session_index(self):
"""
Returns the SessionIndex from the AuthnStatement.
Expand Down
14 changes: 11 additions & 3 deletions src/onelogin/saml2/logout_request.py
Expand Up @@ -29,7 +29,7 @@ class OneLogin_Saml2_Logout_Request(object):
"""

def __init__(self, settings, request=None, name_id=None, session_index=None, nq=None):
def __init__(self, settings, request=None, name_id=None, session_index=None, nq=None, name_id_format=None):
"""
Constructs the Logout Request object.
Expand All @@ -47,6 +47,9 @@ def __init__(self, settings, request=None, name_id=None, session_index=None, nq=
:param nq: IDP Name Qualifier
:type: string
:param name_id_format: The NameID Format that will be set in the LogoutRequest.
:type: string
"""
self.__settings = settings
self.__error = None
Expand All @@ -67,7 +70,10 @@ def __init__(self, settings, request=None, name_id=None, session_index=None, nq=
cert = idp_data['x509cert']

if name_id is not None:
nameIdFormat = sp_data['NameIDFormat']
if name_id_format is not None:
nameIdFormat = name_id_format
else:
nameIdFormat = sp_data['NameIDFormat']
spNameQualifier = None
else:
name_id = idp_data['entityId']
Expand All @@ -78,7 +84,9 @@ def __init__(self, settings, request=None, name_id=None, session_index=None, nq=
name_id,
spNameQualifier,
nameIdFormat,
cert
cert,
False,
nq
)

if session_index:
Expand Down
13 changes: 13 additions & 0 deletions src/onelogin/saml2/response.py
Expand Up @@ -457,6 +457,19 @@ def get_nameid(self):
nameid_value = nameid_data['Value']
return nameid_value

def get_nameid_format(self):
"""
Gets the NameID Format provided by the SAML Response from the IdP
:returns: NameID Format
:rtype: string|None
"""
nameid_format = None
nameid_data = self.get_nameid_data()
if nameid_data and 'Format' in nameid_data.keys():
nameid_format = nameid_data['Format']
return nameid_format

def get_session_not_on_or_after(self):
"""
Gets the SessionNotOnOrAfter from the AuthnStatement
Expand Down
92 changes: 92 additions & 0 deletions tests/src/OneLogin/saml2_tests/auth_test.py
Expand Up @@ -857,6 +857,98 @@ def testSetStrict(self):
with self.assertRaises(AssertionError):
auth.set_strict('42')

def testIsAuthenticated(self):
"""
Tests the is_authenticated method of the OneLogin_Saml2_Auth
"""
request_data = self.get_request()
del request_data['get_data']
message = self.file_contents(join(self.data_path, 'responses', 'response1.xml.base64'))
request_data['post_data'] = {
'SAMLResponse': message
}
auth = OneLogin_Saml2_Auth(request_data, old_settings=self.loadSettingsJSON())
auth.process_response()
self.assertFalse(auth.is_authenticated())

message = self.file_contents(join(self.data_path, 'responses', 'valid_response.xml.base64'))
request_data['post_data'] = {
'SAMLResponse': message
}
auth = OneLogin_Saml2_Auth(request_data, old_settings=self.loadSettingsJSON())
auth.process_response()
self.assertTrue(auth.is_authenticated())

def testGetNameId(self):
"""
Tests the get_nameid method of the OneLogin_Saml2_Auth
"""
settings = self.loadSettingsJSON()
request_data = self.get_request()
del request_data['get_data']
message = self.file_contents(join(self.data_path, 'responses', 'response1.xml.base64'))
request_data['post_data'] = {
'SAMLResponse': message
}
auth = OneLogin_Saml2_Auth(request_data, old_settings=settings)
auth.process_response()
self.assertFalse(auth.is_authenticated())
self.assertEqual(auth.get_nameid(), None)

message = self.file_contents(join(self.data_path, 'responses', 'valid_response.xml.base64'))
request_data['post_data'] = {
'SAMLResponse': message
}
auth = OneLogin_Saml2_Auth(request_data, old_settings=settings)
auth.process_response()
self.assertTrue(auth.is_authenticated())
self.assertEqual("492882615acf31c8096b627245d76ae53036c090", auth.get_nameid())

settings_2 = self.loadSettingsJSON('settings2.json')
message = self.file_contents(join(self.data_path, 'responses', 'signed_message_encrypted_assertion2.xml.base64'))
request_data['post_data'] = {
'SAMLResponse': message
}
auth = OneLogin_Saml2_Auth(request_data, old_settings=settings_2)
auth.process_response()
self.assertTrue(auth.is_authenticated())
self.assertEqual("25ddd7d34a7d79db69167625cda56a320adf2876", auth.get_nameid())

def testGetNameIdFormat(self):
"""
Tests the get_nameid_format method of the OneLogin_Saml2_Auth
"""
settings = self.loadSettingsJSON()
request_data = self.get_request()
del request_data['get_data']
message = self.file_contents(join(self.data_path, 'responses', 'response1.xml.base64'))
request_data['post_data'] = {
'SAMLResponse': message
}
auth = OneLogin_Saml2_Auth(request_data, old_settings=settings)
auth.process_response()
self.assertFalse(auth.is_authenticated())
self.assertEqual(auth.get_nameid_format(), None)

message = self.file_contents(join(self.data_path, 'responses', 'valid_response.xml.base64'))
request_data['post_data'] = {
'SAMLResponse': message
}
auth = OneLogin_Saml2_Auth(request_data, old_settings=settings)
auth.process_response()
self.assertTrue(auth.is_authenticated())
self.assertEqual("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", auth.get_nameid_format())

settings_2 = self.loadSettingsJSON('settings2.json')
message = self.file_contents(join(self.data_path, 'responses', 'signed_message_encrypted_assertion2.xml.base64'))
request_data['post_data'] = {
'SAMLResponse': message
}
auth = OneLogin_Saml2_Auth(request_data, old_settings=settings_2)
auth.process_response()
self.assertTrue(auth.is_authenticated())
self.assertEqual("urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified", auth.get_nameid_format())

def testBuildRequestSignature(self):
"""
Tests the build_request_signature method of the OneLogin_Saml2_Auth
Expand Down
58 changes: 58 additions & 0 deletions tests/src/OneLogin/saml2_tests/response_test.py
Expand Up @@ -137,6 +137,64 @@ def testReturnNameId(self):
with self.assertRaisesRegexp(OneLogin_Saml2_ValidationError, 'An empty NameID value found'):
response_9.get_nameid()

def testReturnNameIdFormat(self):
"""
Tests the get_nameid_format method of the OneLogin_Saml2_Response
"""
json_settings = self.loadSettingsJSON()

settings = OneLogin_Saml2_Settings(json_settings)
xml = self.file_contents(join(self.data_path, 'responses', 'response1.xml.base64'))
response = OneLogin_Saml2_Response(settings, xml)
self.assertEqual('urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', response.get_nameid_format())

xml_2 = self.file_contents(join(self.data_path, 'responses', 'response_encrypted_nameid.xml.base64'))
response_2 = OneLogin_Saml2_Response(settings, xml_2)
self.assertEqual('urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified', response_2.get_nameid_format())

xml_3 = self.file_contents(join(self.data_path, 'responses', 'valid_encrypted_assertion.xml.base64'))
response_3 = OneLogin_Saml2_Response(settings, xml_3)
self.assertEqual('urn:oasis:names:tc:SAML:2.0:nameid-format:transient', response_3.get_nameid_format())

xml_4 = self.file_contents(join(self.data_path, 'responses', 'invalids', 'no_nameid.xml.base64'))
response_4 = OneLogin_Saml2_Response(settings, xml_4)
with self.assertRaisesRegexp(OneLogin_Saml2_ValidationError, 'NameID not found in the assertion of the Response'):
response_4.get_nameid_format()

json_settings['security']['wantNameId'] = True
settings = OneLogin_Saml2_Settings(json_settings)

response_5 = OneLogin_Saml2_Response(settings, xml_4)
with self.assertRaisesRegexp(OneLogin_Saml2_ValidationError, 'NameID not found in the assertion of the Response'):
response_5.get_nameid_format()

json_settings['security']['wantNameId'] = False
settings = OneLogin_Saml2_Settings(json_settings)

response_6 = OneLogin_Saml2_Response(settings, xml_4)
nameid_6 = response_6.get_nameid_format()
self.assertIsNone(nameid_6)

del json_settings['security']['wantNameId']
settings = OneLogin_Saml2_Settings(json_settings)

response_7 = OneLogin_Saml2_Response(settings, xml_4)
with self.assertRaisesRegexp(OneLogin_Saml2_ValidationError, 'NameID not found in the assertion of the Response'):
response_7.get_nameid_format()

json_settings['strict'] = True
settings = OneLogin_Saml2_Settings(json_settings)

xml_5 = self.file_contents(join(self.data_path, 'responses', 'invalids', 'wrong_spnamequalifier.xml.base64'))
response_8 = OneLogin_Saml2_Response(settings, xml_5)
with self.assertRaisesRegexp(OneLogin_Saml2_ValidationError, 'The SPNameQualifier value mistmatch the SP entityID value'):
response_8.get_nameid_format()

xml_6 = self.file_contents(join(self.data_path, 'responses', 'invalids', 'empty_nameid.xml.base64'))
response_9 = OneLogin_Saml2_Response(settings, xml_6)
with self.assertRaisesRegexp(OneLogin_Saml2_ValidationError, 'An empty NameID value found'):
response_9.get_nameid_format()

def testGetNameIdData(self):
"""
Tests the get_nameid_data method of the OneLogin_Saml2_Response
Expand Down

0 comments on commit 52e95da

Please sign in to comment.