Skip to content

Commit f95abc5

Browse files
committed
Merge branch 'feature/re-raising-response-validation-exceptions' of https://github.com/quantus/python3-saml into improve_debug
2 parents f011fda + 16e38be commit f95abc5

File tree

6 files changed

+143
-198
lines changed

6 files changed

+143
-198
lines changed

src/onelogin/saml2/logout_request.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,15 @@ def get_session_indexes(request):
212212
session_indexes.append(session_index_node.text)
213213
return session_indexes
214214

215-
def is_valid(self, request_data):
215+
def is_valid(self, request_data, raises=False):
216216
"""
217217
Checks if the Logout Request received is valid
218218
:param request_data: Request Data
219219
:type request_data: dict
220220
221+
:param raises: Optional argument. If true, the function will raise an exception as soon as first validation test fails
222+
:type raises: bool
223+
221224
:return: If the Logout Request is or not valid
222225
:rtype: boolean
223226
"""
@@ -274,6 +277,8 @@ def is_valid(self, request_data):
274277
debug = self.__settings.is_debug_active()
275278
if debug:
276279
print(err)
280+
if raises:
281+
raise
277282
return False
278283

279284
def get_error(self):

src/onelogin/saml2/logout_response.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,15 @@ def get_status(self):
6363
status = entries[0].attrib['Value']
6464
return status
6565

66-
def is_valid(self, request_data, request_id=None):
66+
def is_valid(self, request_data, request_id=None, raises=False):
6767
"""
6868
Determines if the SAML LogoutResponse is valid
6969
:param request_id: The ID of the LogoutRequest sent by this SP to the IdP
7070
:type request_id: string
71+
72+
:param raises: Optional argument. If true, the function will raise an exception as soon as first validation test fails
73+
:type raises: bool
74+
7175
:return: Returns if the SAML LogoutResponse is or not valid
7276
:rtype: boolean
7377
"""
@@ -111,6 +115,8 @@ def is_valid(self, request_data, request_id=None):
111115
debug = self.__settings.is_debug_active()
112116
if debug:
113117
print(err)
118+
if raises:
119+
raise
114120
return False
115121

116122
def __query(self, query):

src/onelogin/saml2/response.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def __init__(self, settings, response):
4747
self.encrypted = True
4848
self.decrypted_document = self.__decrypt_assertion(decrypted_document)
4949

50-
def is_valid(self, request_data, request_id=None):
50+
def is_valid(self, request_data, request_id=None, raises=False):
5151
"""
5252
Validates the response object.
5353
@@ -57,6 +57,9 @@ def is_valid(self, request_data, request_id=None):
5757
:param request_id: Optional argument. The ID of the AuthNRequest sent by this SP to the IdP
5858
:type request_id: string
5959
60+
:param raises: Optional argument. If true, the function will raise an exception as soon as first validation test fails
61+
:type raises: bool
62+
6063
:returns: True if the SAML Response is valid, False if not
6164
:rtype: bool
6265
"""
@@ -226,6 +229,8 @@ def is_valid(self, request_data, request_id=None):
226229
debug = self.__settings.is_debug_active()
227230
if debug:
228231
print(err)
232+
if raises:
233+
raise
229234
return False
230235

231236
def check_status(self):

tests/src/OneLogin/saml2_tests/logout_request_test.py

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,8 @@ def testGetNameIdData(self):
121121
self.assertEqual(expected_name_id_data, name_id_data_2)
122122

123123
request_2 = self.file_contents(join(self.data_path, 'logout_requests', 'logout_request_encrypted_nameid.xml'))
124-
with self.assertRaises(Exception) as context:
124+
with self.assertRaisesRegexp(Exception, 'Key is required in order to decrypt the NameID'):
125125
OneLogin_Saml2_Logout_Request.get_nameid(request_2)
126-
exception = context.exception
127-
self.assertIn("Key is required in order to decrypt the NameID", str(exception))
128126

129127
settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
130128
key = settings.get_sp_key()
@@ -140,16 +138,12 @@ def testGetNameIdData(self):
140138
encrypted_id_nodes = dom_2.getElementsByTagName('saml:EncryptedID')
141139
encrypted_data = encrypted_id_nodes[0].firstChild.nextSibling
142140
encrypted_id_nodes[0].removeChild(encrypted_data)
143-
with self.assertRaises(Exception) as context:
141+
with self.assertRaisesRegexp(Exception, 'Not NameID found in the Logout Request'):
144142
OneLogin_Saml2_Logout_Request.get_nameid(dom_2.toxml(), key)
145-
exception = context.exception
146-
self.assertIn("Not NameID found in the Logout Request", str(exception))
147143

148144
inv_request = self.file_contents(join(self.data_path, 'logout_requests', 'invalids', 'no_nameId.xml'))
149-
with self.assertRaises(Exception) as context:
145+
with self.assertRaisesRegexp(Exception, 'Not NameID found in the Logout Request'):
150146
OneLogin_Saml2_Logout_Request.get_nameid(inv_request)
151-
exception = context.exception
152-
self.assertIn("Not NameID found in the Logout Request", str(exception))
153147

154148
def testGetNameId(self):
155149
"""
@@ -160,10 +154,8 @@ def testGetNameId(self):
160154
self.assertEqual(name_id, 'ONELOGIN_1e442c129e1f822c8096086a1103c5ee2c7cae1c')
161155

162156
request_2 = self.file_contents(join(self.data_path, 'logout_requests', 'logout_request_encrypted_nameid.xml'))
163-
with self.assertRaises(Exception) as context:
157+
with self.assertRaisesRegexp(Exception, 'Key is required in order to decrypt the NameID'):
164158
OneLogin_Saml2_Logout_Request.get_nameid(request_2)
165-
exception = context.exception
166-
self.assertIn("Key is required in order to decrypt the NameID", str(exception))
167159

168160
settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
169161
key = settings.get_sp_key()
@@ -242,12 +234,9 @@ def testIsInvalidIssuer(self):
242234
self.assertTrue(logout_request.is_valid(request_data))
243235

244236
settings.set_strict(True)
245-
try:
246-
logout_request2 = OneLogin_Saml2_Logout_Request(settings, OneLogin_Saml2_Utils.b64encode(request))
247-
valid = logout_request2.is_valid(request_data)
248-
self.assertFalse(valid)
249-
except Exception as e:
250-
self.assertIn('Invalid issuer in the Logout Request', str(e))
237+
logout_request2 = OneLogin_Saml2_Logout_Request(settings, OneLogin_Saml2_Utils.b64encode(request))
238+
with self.assertRaisesRegexp(Exception, 'Invalid issuer in the Logout Request'):
239+
logout_request2.is_valid(request_data, raises=True)
251240

252241
def testIsInvalidDestination(self):
253242
"""
@@ -264,12 +253,9 @@ def testIsInvalidDestination(self):
264253
self.assertTrue(logout_request.is_valid(request_data))
265254

266255
settings.set_strict(True)
267-
try:
268-
logout_request2 = OneLogin_Saml2_Logout_Request(settings, OneLogin_Saml2_Utils.b64encode(request))
269-
valid = logout_request2.is_valid(request_data)
270-
self.assertFalse(valid)
271-
except Exception as e:
272-
self.assertIn('The LogoutRequest was received at', str(e))
256+
logout_request2 = OneLogin_Saml2_Logout_Request(settings, OneLogin_Saml2_Utils.b64encode(request))
257+
with self.assertRaisesRegexp(Exception, 'The LogoutRequest was received at'):
258+
logout_request2.is_valid(request_data, raises=True)
273259

274260
dom = parseString(request)
275261
dom.documentElement.setAttribute('Destination', None)
@@ -298,12 +284,9 @@ def testIsInvalidNotOnOrAfter(self):
298284
self.assertTrue(logout_request.is_valid(request_data))
299285

300286
settings.set_strict(True)
301-
try:
302-
logout_request2 = OneLogin_Saml2_Logout_Request(settings, OneLogin_Saml2_Utils.b64encode(request))
303-
valid = logout_request2.is_valid(request_data)
304-
self.assertFalse(valid)
305-
except Exception as e:
306-
self.assertIn('Timing issues (please check your clock settings)', str(e))
287+
logout_request2 = OneLogin_Saml2_Logout_Request(settings, OneLogin_Saml2_Utils.b64encode(request))
288+
with self.assertRaisesRegexp(Exception, 'Timing issues \(please check your clock settings\)'):
289+
logout_request2.is_valid(request_data, raises=True)
307290

308291
def testIsValid(self):
309292
"""
@@ -336,3 +319,19 @@ def testIsValid(self):
336319
request = request.replace('http://stuff.com/endpoints/endpoints/sls.php', current_url)
337320
logout_request5 = OneLogin_Saml2_Logout_Request(settings, OneLogin_Saml2_Utils.b64encode(request))
338321
self.assertTrue(logout_request5.is_valid(request_data))
322+
323+
def testIsValidRaisesExceptionWhenRaisesArgumentIsTrue(self):
324+
request = OneLogin_Saml2_Utils.b64encode('<xml>invalid</xml>')
325+
request_data = {
326+
'http_host': 'example.com',
327+
'script_name': 'index.html',
328+
}
329+
settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
330+
settings.set_strict(True)
331+
332+
logout_request = OneLogin_Saml2_Logout_Request(settings, request)
333+
334+
self.assertFalse(logout_request.is_valid(request_data))
335+
336+
with self.assertRaises(Exception):
337+
logout_request.is_valid(request_data, raises=True)

tests/src/OneLogin/saml2_tests/logout_response_test.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,8 @@ def testIsInValidIssuer(self):
201201

202202
settings.set_strict(True)
203203
response_2 = OneLogin_Saml2_Logout_Response(settings, message)
204-
try:
205-
valid = response_2.is_valid(request_data)
206-
self.assertFalse(valid)
207-
except Exception as e:
208-
self.assertIn('Invalid issuer in the Logout Request', str(e))
204+
with self.assertRaisesRegexp(Exception, 'Invalid issuer in the Logout Request'):
205+
response_2.is_valid(request_data, raises=True)
209206

210207
def testIsInValidDestination(self):
211208
"""
@@ -226,11 +223,8 @@ def testIsInValidDestination(self):
226223

227224
settings.set_strict(True)
228225
response_2 = OneLogin_Saml2_Logout_Response(settings, message)
229-
try:
230-
valid = response_2.is_valid(request_data)
231-
self.assertFalse(valid)
232-
except Exception as e:
233-
self.assertIn('The LogoutRequest was received at', str(e))
226+
with self.assertRaisesRegexp(Exception, 'The LogoutRequest was received at'):
227+
response_2.is_valid(request_data, raises=True)
234228

235229
# Empty destination
236230
dom = parseString(OneLogin_Saml2_Utils.decode_base64_and_inflate(message))
@@ -264,11 +258,8 @@ def testIsValid(self):
264258

265259
settings.set_strict(True)
266260
response_2 = OneLogin_Saml2_Logout_Response(settings, message)
267-
try:
268-
valid = response_2.is_valid(request_data)
269-
self.assertFalse(valid)
270-
except Exception as e:
271-
self.assertIn('The LogoutRequest was received at', str(e))
261+
with self.assertRaisesRegexp(Exception, 'The LogoutRequest was received at'):
262+
response_2.is_valid(request_data, raises=True)
272263

273264
plain_message = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(message))
274265
current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data)
@@ -277,3 +268,20 @@ def testIsValid(self):
277268

278269
response_3 = OneLogin_Saml2_Logout_Response(settings, message_3)
279270
self.assertTrue(response_3.is_valid(request_data))
271+
272+
def testIsValidRaisesExceptionWhenRaisesArgumentIsTrue(self):
273+
message = OneLogin_Saml2_Utils.deflate_and_base64_encode('<xml>invalid</xml>')
274+
request_data = {
275+
'http_host': 'example.com',
276+
'script_name': 'index.html',
277+
'get_data': {}
278+
}
279+
settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
280+
settings.set_strict(True)
281+
282+
response = OneLogin_Saml2_Logout_Response(settings, message)
283+
284+
self.assertFalse(response.is_valid(request_data))
285+
286+
with self.assertRaises(Exception):
287+
response.is_valid(request_data, raises=True)

0 commit comments

Comments
 (0)