From e0241aba38b2da645745f6b75c7acd7dbf58ffe8 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Mon, 31 Jan 2022 13:19:41 +0200 Subject: [PATCH] Use Python 3.6+ ISO time functions Refs #289 --- src/onelogin/saml2/utils.py | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/src/onelogin/saml2/utils.py b/src/onelogin/saml2/utils.py index ad14f4f7..3d7f6c85 100644 --- a/src/onelogin/saml2/utils.py +++ b/src/onelogin/saml2/utils.py @@ -10,7 +10,6 @@ import base64 import warnings from copy import deepcopy -import calendar from datetime import datetime from hashlib import sha1, sha256, sha384, sha512 from isodate import parse_duration as duration_parser @@ -58,10 +57,6 @@ class OneLogin_Saml2_Utils: RESPONSE_SIGNATURE_XPATH = '/samlp:Response/ds:Signature' ASSERTION_SIGNATURE_XPATH = '/samlp:Response/saml:Assertion/ds:Signature' - TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" - TIME_FORMAT_2 = "%Y-%m-%dT%H:%M:%S.%fZ" - 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?$') - @staticmethod def escape_url(url, lowercase_urlencoding=False): """ @@ -377,7 +372,11 @@ def generate_unique_id(): def parse_time_to_SAML(time): r""" Converts a UNIX timestamp to SAML2 timestamp on the form - yyyy-mm-ddThh:mm:ss(\.s+)?Z. + yyyy-mm-ddThh:mm:ss. + + > All SAML time values have the type "xs:dateTime", + > which is built in to the W3C XML Schema Datatypes specification, + > and MUST be expressed in UTC form, with no time zone component. :param time: The time we should convert (DateTime). :type: string @@ -385,14 +384,13 @@ def parse_time_to_SAML(time): :return: SAML2 timestamp. :rtype: string """ - data = datetime.utcfromtimestamp(float(time)) - return data.strftime(OneLogin_Saml2_Utils.TIME_FORMAT) + return datetime.utcfromtimestamp(float(time)).isoformat(timespec="seconds") @staticmethod def parse_SAML_to_time(timestr): r""" - Converts a SAML2 timestamp on the form yyyy-mm-ddThh:mm:ss(\.s+)?Z - to a UNIX timestamp. The sub-second part is ignored. + Converts a SAML2 timestamp to a UNIX timestamp. + The sub-second part is truncated. :param timestr: The time we should convert (SAML Timestamp). :type: string @@ -400,18 +398,7 @@ def parse_SAML_to_time(timestr): :return: Converted to a unix timestamp. :rtype: int """ - try: - data = datetime.strptime(timestr, OneLogin_Saml2_Utils.TIME_FORMAT) - except ValueError: - try: - data = datetime.strptime(timestr, OneLogin_Saml2_Utils.TIME_FORMAT_2) - except ValueError: - elem = OneLogin_Saml2_Utils.TIME_FORMAT_WITH_FRAGMENT.match(timestr) - if not elem: - raise Exception("time data %s does not match format %s" % (timestr, r'yyyy-mm-ddThh:mm:ss(\.s+)?Z')) - data = datetime.strptime(elem.groups()[0] + "Z", OneLogin_Saml2_Utils.TIME_FORMAT) - - return calendar.timegm(data.utctimetuple()) + return int(datetime.fromisoformat(timestr).timestamp()) @staticmethod def now(): @@ -419,7 +406,7 @@ def now(): :return: unix timestamp of actual time. :rtype: int """ - return calendar.timegm(datetime.utcnow().utctimetuple()) + return int(datetime.now().timestamp()) @staticmethod def parse_duration(duration, timestamp=None): @@ -444,7 +431,7 @@ def parse_duration(duration, timestamp=None): data = datetime.utcnow() + timedelta else: data = datetime.utcfromtimestamp(timestamp) + timedelta - return calendar.timegm(data.utctimetuple()) + return int(data.timestamp()) @staticmethod def get_expire_time(cache_duration=None, valid_until=None):