Skip to content

Commit 8b87e5f

Browse files
committed
Fix #250. Allow any number of decimal places for seconds on SAML datetimes
1 parent 102e368 commit 8b87e5f

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

src/onelogin/saml2/utils.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ class OneLogin_Saml2_Utils(object):
8989
RESPONSE_SIGNATURE_XPATH = '/samlp:Response/ds:Signature'
9090
ASSERTION_SIGNATURE_XPATH = '/samlp:Response/saml:Assertion/ds:Signature'
9191

92+
TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
93+
TIME_FORMAT_2 = "%Y-%m-%dT%H:%M:%S.%fZ"
94+
TIME_FORMAT_WITH_FRAGMENT = re.compile(
95+
"^(\d{4,4}-\d{2,2}-\d{2,2}T\d{2,2}:\d{2,2}:\d{2,2})(\.\d*)?Z?$")
96+
9297
@staticmethod
9398
def decode_base64_and_inflate(value):
9499
"""
@@ -445,7 +450,7 @@ def parse_time_to_SAML(time):
445450
:rtype: string
446451
"""
447452
data = datetime.utcfromtimestamp(float(time))
448-
return data.strftime('%Y-%m-%dT%H:%M:%SZ')
453+
return data.strftime(OneLogin_Saml2_Utils.TIME_FORMAT)
449454

450455
@staticmethod
451456
def parse_SAML_to_time(timestr):
@@ -460,9 +465,16 @@ def parse_SAML_to_time(timestr):
460465
:rtype: int
461466
"""
462467
try:
463-
data = datetime.strptime(timestr, '%Y-%m-%dT%H:%M:%SZ')
468+
data = datetime.strptime(timestr, OneLogin_Saml2_Utils.TIME_FORMAT)
464469
except ValueError:
465-
data = datetime.strptime(timestr, '%Y-%m-%dT%H:%M:%S.%fZ')
470+
try:
471+
data = datetime.strptime(timestr, OneLogin_Saml2_Utils.TIME_FORMAT_2)
472+
except ValueError:
473+
elem = OneLogin_Saml2_Utils.TIME_FORMAT_WITH_FRAGMENT.match(timestr)
474+
if not elem:
475+
raise Exception("time data %s does not match format %s" % (timestr, "yyyy-mm-ddThh:mm:ss(\.s+)?Z"))
476+
data = datetime.strptime(elem.groups()[0] + "Z", OneLogin_Saml2_Utils.TIME_FORMAT)
477+
466478
return calendar.timegm(data.utctimetuple())
467479

468480
@staticmethod

tests/src/OneLogin/saml2_tests/utils_test.py

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

479+
# Now test if toolkit supports microseconds
480+
saml_time3 = '2013-12-10T04:39:31.120240Z'
481+
self.assertEqual(time, OneLogin_Saml2_Utils.parse_SAML_to_time(saml_time3))
482+
483+
# Now test if toolkit supports nanoseconds
484+
saml_time4 = '2013-12-10T04:39:31.120240360Z'
485+
self.assertEqual(time, OneLogin_Saml2_Utils.parse_SAML_to_time(saml_time4))
486+
479487
def testParseTime2SAML(self):
480488
"""
481489
Tests the parse_time_to_SAML method of the OneLogin_Saml2_Utils

0 commit comments

Comments
 (0)