Skip to content

Commit 6e178d3

Browse files
committed
Add get_last_message_id and get_last_assertion_id
I tried to follow the pattern used in php-saml
1 parent 16cd67c commit 6e178d3

File tree

4 files changed

+87
-2
lines changed

4 files changed

+87
-2
lines changed

src/onelogin/saml2/auth.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def __init__(self, request_data, old_settings=None, custom_base_path=None):
6161
self.__errors = []
6262
self.__error_reason = None
6363
self.__last_request_id = None
64+
self.__last_message_id = None
65+
self.__last_assertion_id = None
6466
self.__last_request = None
6567
self.__last_response = None
6668

@@ -104,6 +106,8 @@ def process_response(self, request_id=None):
104106
self.__nameid_format = response.get_nameid_format()
105107
self.__session_index = response.get_session_index()
106108
self.__session_expiration = response.get_session_not_on_or_after()
109+
self.__last_message_id = response.get_id()
110+
self.__last_assertion_id = response.get_assertion_id()
107111
self.__authenticated = True
108112

109113
else:
@@ -143,8 +147,10 @@ def process_slo(self, keep_local_session=False, request_id=None, delete_session_
143147
self.__error_reason = logout_response.get_error()
144148
elif logout_response.get_status() != OneLogin_Saml2_Constants.STATUS_SUCCESS:
145149
self.__errors.append('logout_not_success')
146-
elif not keep_local_session:
147-
OneLogin_Saml2_Utils.delete_local_session(delete_session_cb)
150+
else:
151+
self.__last_message_id = logout_response.id
152+
if not keep_local_session:
153+
OneLogin_Saml2_Utils.delete_local_session(delete_session_cb)
148154

149155
elif get_data and 'SAMLRequest' in get_data:
150156
logout_request = OneLogin_Saml2_Logout_Request(self.__settings, get_data['SAMLRequest'])
@@ -160,6 +166,7 @@ def process_slo(self, keep_local_session=False, request_id=None, delete_session_
160166
OneLogin_Saml2_Utils.delete_local_session(delete_session_cb)
161167

162168
in_response_to = logout_request.id
169+
self.__last_message_id = logout_request.id
163170
response_builder = OneLogin_Saml2_Logout_Response(self.__settings)
164171
response_builder.build(in_response_to)
165172
self.__last_response = response_builder.get_xml()
@@ -286,6 +293,20 @@ def get_last_request_id(self):
286293
"""
287294
return self.__last_request_id
288295

296+
def get_last_message_id(self):
297+
"""
298+
:returns: The ID of the last Response SAML message processed.
299+
:rtype: string
300+
"""
301+
return self.__last_message_id
302+
303+
def get_last_assertion_id(self):
304+
"""
305+
:returns: The ID of the last assertion processed.
306+
:rtype: string
307+
"""
308+
return self.__last_assertion_id
309+
289310
def login(self, return_to=None, force_authn=False, is_passive=False, set_nameid_policy=True):
290311
"""
291312
Initiates the SSO process.

src/onelogin/saml2/logout_response.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ def __init__(self, settings, response=None):
3535
"""
3636
self.__settings = settings
3737
self.__error = None
38+
self.id = None
3839

3940
if response is not None:
4041
self.__logout_response = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(response))
4142
self.document = OneLogin_Saml2_XML.to_etree(self.__logout_response)
43+
self.id = self.document.get('ID', None)
4244

4345
def get_issuer(self):
4446
"""

src/onelogin/saml2/response.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,3 +786,22 @@ def get_xml_document(self):
786786
return self.decrypted_document
787787
else:
788788
return self.document
789+
790+
def get_id(self):
791+
"""
792+
:returns: the ID of the response
793+
:rtype: string
794+
"""
795+
return self.document.get('ID', None)
796+
797+
def get_assertion_id(self):
798+
"""
799+
:returns: the ID of the assertion in the response
800+
:rtype: string
801+
"""
802+
if not self.validate_num_assertions():
803+
raise OneLogin_Saml2_ValidationError(
804+
'SAML Response must contain 1 assertion',
805+
OneLogin_Saml2_ValidationError.WRONG_NUMBER_OF_ASSERTIONS
806+
)
807+
return self.__query_assertion('')[0].get('ID', None)

tests/src/OneLogin/saml2_tests/auth_test.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,3 +1259,46 @@ def testGetLastLogoutResponse(self):
12591259
auth = OneLogin_Saml2_Auth(message_wrapper, old_settings=settings)
12601260
auth.process_slo()
12611261
self.assertEqual(response, auth.get_last_response_xml())
1262+
1263+
def testGetLastMessageAndAssertionId(self):
1264+
"""
1265+
Tests the get_last_message_id and get_last_assertion_id of the OneLogin_Saml2_Auth class
1266+
Case Valid Response
1267+
"""
1268+
request_data = self.get_request()
1269+
message = self.file_contents(join(self.data_path, 'responses', 'valid_response.xml.base64'))
1270+
del request_data['get_data']
1271+
request_data['post_data'] = {
1272+
'SAMLResponse': message
1273+
}
1274+
auth = OneLogin_Saml2_Auth(request_data, old_settings=self.loadSettingsJSON())
1275+
1276+
auth.process_response()
1277+
self.assertEqual(auth.get_last_message_id(), 'pfxcc31568b-c46d-ff75-ba2e-5303484980da')
1278+
self.assertEqual(auth.get_last_assertion_id(), 'pfx08c2a6bb-7ee4-8dc2-8fe2-f055eed93de4')
1279+
1280+
def testGetIdFromLogoutRequest(self):
1281+
"""
1282+
Tests the get_last_message_id of the OneLogin_Saml2_Auth class
1283+
Case Valid Logout request
1284+
"""
1285+
settings = self.loadSettingsJSON()
1286+
request = self.file_contents(join(self.data_path, 'logout_requests', 'logout_request.xml'))
1287+
message = OneLogin_Saml2_Utils.deflate_and_base64_encode(request)
1288+
message_wrapper = {'get_data': {'SAMLRequest': message}}
1289+
auth = OneLogin_Saml2_Auth(message_wrapper, old_settings=settings)
1290+
auth.process_slo()
1291+
self.assertIn(auth.get_last_message_id(), 'ONELOGIN_21584ccdfaca36a145ae990442dcd96bfe60151e')
1292+
1293+
def testGetIdFromLogoutResponse(self):
1294+
"""
1295+
Tests the get_last_message_id of the OneLogin_Saml2_Auth class
1296+
Case Valid Logout response
1297+
"""
1298+
settings = self.loadSettingsJSON()
1299+
response = self.file_contents(join(self.data_path, 'logout_responses', 'logout_response.xml'))
1300+
message = OneLogin_Saml2_Utils.deflate_and_base64_encode(response)
1301+
message_wrapper = {'get_data': {'SAMLResponse': message}}
1302+
auth = OneLogin_Saml2_Auth(message_wrapper, old_settings=settings)
1303+
auth.process_slo()
1304+
self.assertIn(auth.get_last_message_id(), '_f9ee61bd9dbf63606faa9ae3b10548d5b3656fb859')

0 commit comments

Comments
 (0)