utils.token: Use time.time to generate the timestamps

Use `time.time()` rather than `timezone.now()` for generating the unix
timestamps.  This avoids conversion between year-month-day-hh-mm-ss
formatted timestamp vs. unix timestamp and is therefore simpler and more
robust.

Add a test case for this too and amend test_token_endpoint, since it
used to mock timezone.now, but now it needs to mock time.time.
This commit is contained in:
Tuomas Suutari 2016-12-07 14:14:37 +02:00
parent 5e3876f0c6
commit 65538b0f7d
3 changed files with 47 additions and 12 deletions

View file

@ -3,7 +3,7 @@ import time
import uuid import uuid
from Cryptodome.PublicKey.RSA import importKey from Cryptodome.PublicKey.RSA import importKey
from django.utils import timezone from django.utils import dateformat, timezone
from jwkest.jwk import RSAKey as jwk_RSAKey from jwkest.jwk import RSAKey as jwk_RSAKey
from jwkest.jwk import SYMKey from jwkest.jwk import SYMKey
from jwkest.jws import JWS from jwkest.jws import JWS
@ -29,11 +29,11 @@ def create_id_token(user, aud, nonce='', at_hash='', request=None, scope=[]):
expires_in = settings.get('OIDC_IDTOKEN_EXPIRE') expires_in = settings.get('OIDC_IDTOKEN_EXPIRE')
# Convert datetimes into timestamps. # Convert datetimes into timestamps.
now = timezone.now() now = int(time.time())
iat_time = int(time.mktime(now.timetuple())) iat_time = now
exp_time = int(time.mktime((now + timedelta(seconds=expires_in)).timetuple())) exp_time = int(now + 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 = int(dateformat.format(user_auth_time, 'U'))
dic = { dic = {
'iss': get_issuer(request=request), 'iss': get_issuer(request=request),

View file

@ -1,5 +1,5 @@
from datetime import timedelta
import json import json
import time
import uuid import uuid
from base64 import b64encode from base64 import b64encode
@ -15,7 +15,6 @@ from django.test import (
override_settings, override_settings,
) )
from django.test import TestCase from django.test import TestCase
from django.utils import timezone
from jwkest.jwk import KEYS from jwkest.jwk import KEYS
from jwkest.jws import JWS from jwkest.jws import JWS
from jwkest.jwt import JWT from jwkest.jwt import JWT
@ -164,9 +163,9 @@ class TokenTestCase(TestCase):
# Retrieve refresh token # Retrieve refresh token
code = self._create_code() code = self._create_code()
post_data = self._auth_code_post_data(code=code.code) post_data = self._auth_code_post_data(code=code.code)
real_now = timezone.now start_time = time.time()
with patch('oidc_provider.lib.utils.token.timezone.now') as now: with patch('oidc_provider.lib.utils.token.time.time') as time_func:
now.return_value = real_now() time_func.return_value = start_time
response = self._post_request(post_data) response = self._post_request(post_data)
response_dic1 = json.loads(response.content.decode('utf-8')) response_dic1 = json.loads(response.content.decode('utf-8'))
@ -174,8 +173,8 @@ class TokenTestCase(TestCase):
# Use refresh token to obtain new token # Use refresh token to obtain new token
post_data = self._refresh_token_post_data(response_dic1['refresh_token']) post_data = self._refresh_token_post_data(response_dic1['refresh_token'])
with patch('oidc_provider.lib.utils.token.timezone.now') as now: with patch('oidc_provider.lib.utils.token.time.time') as time_func:
now.return_value = real_now() + timedelta(minutes=10) time_func.return_value = start_time + 600
response = self._post_request(post_data) response = self._post_request(post_data)
response_dic2 = json.loads(response.content.decode('utf-8')) response_dic2 = json.loads(response.content.decode('utf-8'))
@ -189,6 +188,8 @@ class TokenTestCase(TestCase):
self.assertEqual(id_token1['iss'], id_token2['iss']) self.assertEqual(id_token1['iss'], id_token2['iss'])
self.assertEqual(id_token1['sub'], id_token2['sub']) self.assertEqual(id_token1['sub'], id_token2['sub'])
self.assertNotEqual(id_token1['iat'], id_token2['iat']) self.assertNotEqual(id_token1['iat'], id_token2['iat'])
self.assertEqual(id_token1['iat'], int(start_time))
self.assertEqual(id_token2['iat'], int(start_time + 600))
self.assertEqual(id_token1['aud'], id_token2['aud']) self.assertEqual(id_token1['aud'], id_token2['aud'])
self.assertEqual(id_token1['auth_time'], id_token2['auth_time']) self.assertEqual(id_token1['auth_time'], id_token2['auth_time'])
self.assertEqual(id_token1.get('azp'), id_token2.get('azp')) self.assertEqual(id_token1.get('azp'), id_token2.get('azp'))

View file

@ -1,6 +1,12 @@
import time
from datetime import datetime
from django.test import TestCase from django.test import TestCase
from django.utils import timezone
from oidc_provider.lib.utils.common import get_issuer from oidc_provider.lib.utils.common import get_issuer
from oidc_provider.lib.utils.token import create_id_token
from oidc_provider.tests.app.utils import create_fake_user
class Request(object): class Request(object):
@ -42,3 +48,31 @@ 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 timestamp_to_datetime(timestamp):
tz = timezone.get_current_timezone()
return datetime.fromtimestamp(timestamp, tz=tz)
class TokenTest(TestCase):
def setUp(self):
self.user = create_fake_user()
def test_create_id_token(self):
start_time = int(time.time())
login_timestamp = start_time - 1234
self.user.last_login = timestamp_to_datetime(login_timestamp)
id_token_data = create_id_token(self.user, aud='test-aud')
iat = id_token_data['iat']
self.assertEqual(type(iat), int)
self.assertGreaterEqual(iat, start_time)
self.assertLessEqual(iat - start_time, 5) # Can't take more than 5 s
self.assertEqual(id_token_data, {
'aud': 'test-aud',
'auth_time': login_timestamp,
'exp': iat + 600,
'iat': iat,
'iss': 'http://localhost:8000/openid',
'sub': str(self.user.id),
})