Skip to content

Commit 5f162dc

Browse files
committed
Allow any number of decimal places for seconds on SAML datetimes
1 parent c13e998 commit 5f162dc

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

src/onelogin/saml2/utils.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ class OneLogin_Saml2_Utils(object):
6565
RESPONSE_SIGNATURE_XPATH = '/samlp:Response/ds:Signature'
6666
ASSERTION_SIGNATURE_XPATH = '/samlp:Response/saml:Assertion/ds:Signature'
6767

68+
TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
69+
TIME_FORMAT_2 = "%Y-%m-%dT%H:%M:%S.%fZ"
70+
TIME_FORMAT_WITH_FRAGMENT = re.compile(r'^(\d{4,4}-\d{2,2}-\d{2,2}T\d{2,2}:\d{2,2}:\d{2,2})(\.\d*)?Z?$')
71+
6872
@staticmethod
6973
def escape_url(url, lowercase_urlencoding=False):
7074
"""
@@ -401,7 +405,7 @@ def parse_time_to_SAML(time):
401405
:rtype: string
402406
"""
403407
data = datetime.utcfromtimestamp(float(time))
404-
return data.strftime('%Y-%m-%dT%H:%M:%SZ')
408+
return data.strftime(OneLogin_Saml2_Utils.TIME_FORMAT)
405409

406410
@staticmethod
407411
def parse_SAML_to_time(timestr):
@@ -416,9 +420,16 @@ def parse_SAML_to_time(timestr):
416420
:rtype: int
417421
"""
418422
try:
419-
data = datetime.strptime(timestr, '%Y-%m-%dT%H:%M:%SZ')
423+
data = datetime.strptime(timestr, OneLogin_Saml2_Utils.TIME_FORMAT)
420424
except ValueError:
421-
data = datetime.strptime(timestr, '%Y-%m-%dT%H:%M:%S.%fZ')
425+
try:
426+
data = datetime.strptime(timestr, OneLogin_Saml2_Utils.TIME_FORMAT_2)
427+
except ValueError:
428+
elem = OneLogin_Saml2_Utils.TIME_FORMAT_WITH_FRAGMENT.match(timestr)
429+
if not elem:
430+
raise Exception("time data %s does not match format %s" % (timestr, r'yyyy-mm-ddThh:mm:ss(\.s+)?Z'))
431+
data = datetime.strptime(elem.groups()[0] + "Z", OneLogin_Saml2_Utils.TIME_FORMAT)
432+
422433
return calendar.timegm(data.utctimetuple())
423434

424435
@staticmethod

tests/src/OneLogin/saml2_tests/utils_test.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,14 @@ def testParseSAML2Time(self):
450450
saml_time2 = '2013-12-10T04:39:31.120Z'
451451
self.assertEqual(time, OneLogin_Saml2_Utils.parse_SAML_to_time(saml_time2))
452452

453+
# Now test if toolkit supports microseconds
454+
saml_time3 = '2013-12-10T04:39:31.120240Z'
455+
self.assertEqual(time, OneLogin_Saml2_Utils.parse_SAML_to_time(saml_time3))
456+
457+
# Now test if toolkit supports nanoseconds
458+
saml_time4 = '2013-12-10T04:39:31.120240360Z'
459+
self.assertEqual(time, OneLogin_Saml2_Utils.parse_SAML_to_time(saml_time4))
460+
453461
def testParseTime2SAML(self):
454462
"""
455463
Tests the parse_time_to_SAML method of the OneLogin_Saml2_Utils

0 commit comments

Comments
 (0)