Fix timestamps computing in tokens

The timestamp of timezone-aware datetimes was offset by the value of their timezone.
This commit is contained in:
Brice Gelineau 2016-11-30 15:22:58 +01:00
parent 11ef97fdbb
commit 975eb0163f
3 changed files with 40 additions and 7 deletions

View file

@ -1,5 +1,9 @@
import datetime
import time
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import HttpResponse from django.http import HttpResponse
from django.utils import timezone
from oidc_provider import settings from oidc_provider import settings
@ -98,3 +102,19 @@ def default_idtoken_processing_hook(id_token, user):
:rtype dict :rtype dict
""" """
return id_token return id_token
def to_timestamp(dt):
"""
Convert a datetime to an integer timestamp.
Inspired from Py3 code, can be replaced by ``int(dt.timestamp())``
when Py2 is not supported anymore.
Note: we assume the timezone of naive datetimes is the one of the
system, not settings.TIME_ZONE as this setting may not have been
set by the user.
"""
if timezone.is_aware(dt):
return int((dt - datetime.datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds())
else:
return int(time.mktime(dt.timetuple()))

View file

@ -1,5 +1,4 @@
from datetime import timedelta from datetime import timedelta
import time
import uuid import uuid
from Cryptodome.PublicKey.RSA import importKey from Cryptodome.PublicKey.RSA import importKey
@ -9,7 +8,7 @@ from jwkest.jwk import SYMKey
from jwkest.jws import JWS from jwkest.jws import JWS
from jwkest.jwt import JWT from jwkest.jwt import JWT
from oidc_provider.lib.utils.common import get_issuer from oidc_provider.lib.utils.common import get_issuer, to_timestamp
from oidc_provider.models import ( from oidc_provider.models import (
Code, Code,
RSAKey, RSAKey,
@ -30,10 +29,10 @@ def create_id_token(user, aud, nonce='', at_hash='', request=None, scope=[]):
# Convert datetimes into timestamps. # Convert datetimes into timestamps.
now = timezone.now() now = timezone.now()
iat_time = int(time.mktime(now.timetuple())) iat_time = to_timestamp(now)
exp_time = int(time.mktime((now + timedelta(seconds=expires_in)).timetuple())) exp_time = to_timestamp(now + timedelta(seconds=expires_in))
user_auth_time = user.last_login or user.date_joined user_auth_time = user.last_login or user.date_joined
auth_time = int(time.mktime(user_auth_time.timetuple())) auth_time = to_timestamp(user_auth_time)
dic = { dic = {
'iss': get_issuer(request=request), 'iss': get_issuer(request=request),

View file

@ -1,6 +1,10 @@
from django.test import TestCase import datetime
from oidc_provider.lib.utils.common import get_issuer from django.test import TestCase
from django.utils import timezone
from django.utils import six
from oidc_provider.lib.utils.common import get_issuer, to_timestamp
class Request(object): class Request(object):
@ -42,3 +46,13 @@ class CommonTest(TestCase):
self.assertEqual(get_issuer(site_url='http://127.0.0.1:9000', self.assertEqual(get_issuer(site_url='http://127.0.0.1:9000',
request=request), request=request),
'http://127.0.0.1:9000/openid') 'http://127.0.0.1:9000/openid')
def test_to_timestamp(self):
if not six.PY2:
naive_dt = datetime.datetime.now()
self.assertEqual(to_timestamp(naive_dt), int(naive_dt.timestamp()))
aware_dt = datetime.datetime(2016, 3, 2, 14, 2, 6, 123, timezone.utc)
self.assertEqual(to_timestamp(aware_dt), 1456927326)
if not six.PY2:
self.assertEqual(to_timestamp(aware_dt), int(aware_dt.timestamp()))