From 3d49a2e7a5f883df4b737faa11bca9b848298511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Robles?= Date: Thu, 8 Aug 2024 10:39:27 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Separation=20of=20voting=20session?= =?UTF-8?q?=20time=20and=20bearer=20token=20lifetime=20(#351)=20(#355)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parent issue: https://github.com/sequentech/meta/issues/762 --- iam/api/decorators.py | 5 ++- iam/api/migrations/0054_token_duration.py | 23 ++++++++++ iam/api/models.py | 30 +++++++++++-- iam/api/tasks.py | 42 +++++++++++-------- iam/api/test_data.py | 7 ++-- iam/api/tests.py | 20 +++++---- iam/api/views.py | 14 +++---- iam/authmethods/m_dnie.py | 2 +- iam/authmethods/m_smart_link.py | 4 +- iam/authmethods/tests.py | 12 +++--- iam/authmethods/utils.py | 19 +++++---- iam/iam/settings.py | 8 +++- iam/iam/test_settings.py | 8 +++- iam/utils.py | 51 +++++++++++++++++------ 14 files changed, 176 insertions(+), 69 deletions(-) create mode 100644 iam/api/migrations/0054_token_duration.py diff --git a/iam/api/decorators.py b/iam/api/decorators.py index db53b16b..265385d9 100644 --- a/iam/api/decorators.py +++ b/iam/api/decorators.py @@ -28,7 +28,7 @@ def get_auth_key(request): key = request.META.get('HTTP_HTTP_AUTH', None) return key -def get_login_user(request): +def get_login_user(request, has_expiry_timestamp = True): key = get_auth_key(request) hmac_token = None @@ -39,6 +39,9 @@ def get_login_user(request): hmac_token = HMACToken(key) user = User.objects.get(username=hmac_token.get_userid()) + if (hmac_token.expiry_timestamp != False) != has_expiry_timestamp: + return None, dict(error_codename="invalid_token_type"), hmac_token + # admin auth event has a different timeout if user.userdata.event_id == settings.ADMIN_AUTH_ID: timeout = settings.ADMIN_TIMEOUT diff --git a/iam/api/migrations/0054_token_duration.py b/iam/api/migrations/0054_token_duration.py new file mode 100644 index 00000000..ce4043ea --- /dev/null +++ b/iam/api/migrations/0054_token_duration.py @@ -0,0 +1,23 @@ +# Generated by Felix Robles on 2024-06-27 06:36 + +from django.db import migrations, models +from django.contrib.postgres.fields import JSONField +import django.core.validators + +class Migration(migrations.Migration): + dependencies = [ + ('api', '0053_authapi_oidc_providers'), + ] + + operations = [ + migrations.AddField( + model_name='authevent', + name='refresh_token_duration_secs', + field=models.IntegerField(default=600, validators=[django.core.validators.MinValueValidator(0)]), + ), + migrations.AddField( + model_name='authevent', + name='access_token_duration_secs', + field=models.IntegerField(default=120, validators=[django.core.validators.MinValueValidator(0)]), + ), + ] diff --git a/iam/api/models.py b/iam/api/models.py index c9b9f157..298fbc79 100644 --- a/iam/api/models.py +++ b/iam/api/models.py @@ -42,7 +42,7 @@ from django.db.models import CharField from django.db.models.functions import Length -from utils import genhmac +from utils import generate_access_token_hmac from api.middleware import CurrentUserMiddleware CharField.register_lookup(Length, 'length') @@ -589,6 +589,30 @@ class AuthEvent(models.Model): ) based_in = models.IntegerField(null=True) # auth_event_id + + refresh_token_duration_secs = models.IntegerField( + default=0, + validators=[ + MinValueValidator(0) + ] + ) + + access_token_duration_secs = models.IntegerField( + default=0, + validators=[ + MinValueValidator(0) + ] + ) + + def get_refresh_token_duration_secs(self): + if self.refresh_token_duration_secs > 0: + return self.refresh_token_duration_secs + is_admin = settings.ADMIN_AUTH_ID == self.id + return settings.ADMIN_TIMEOUT if is_admin else settings.REFRESH_TIMEOUT + + def get_access_token_duration_secs(self): + return self.access_token_duration_secs if self.access_token_duration_secs > 0 else settings.ACCESS_TIMEOUT + # will return true if allow_user_resend is defined and it's True, # false otherwise def check_allow_user_resend(self): @@ -1224,9 +1248,9 @@ def serialize(self): } return d - def get_hmac(self): + def get_hmac(self, validity): msg = ':'.join((self.user.user.username, self.object_type, str(self.object_id), self.perm)) - khmac = genhmac(settings.SHARED_SECRET, msg) + khmac = generate_access_token_hmac(settings.SHARED_SECRET, msg, validity) return khmac def __str__(self): diff --git a/iam/api/tasks.py b/iam/api/tasks.py index 60670254..517943b5 100644 --- a/iam/api/tasks.py +++ b/iam/api/tasks.py @@ -25,7 +25,7 @@ import plugins from authmethods.sms_provider import SMSProvider -from utils import send_codes, genhmac, reproducible_json_dumps +from utils import send_codes, generate_access_token_hmac, reproducible_json_dumps from .models import Action, AuthEvent, BallotBox, TallySheet logger = get_task_logger(__name__) @@ -156,9 +156,10 @@ def launch_tally(auth_event): callback_url, json=[], headers={ - 'Authorization': genhmac( + 'Authorization': generate_access_token_hmac( settings.SHARED_SECRET, - "1:AuthEvent:%s:tally" % auth_event.id + "1:AuthEvent:%s:tally" % auth_event.id, + auth_event.get_refresh_token_duration_secs() ), 'Content-type': 'application/json' } @@ -244,9 +245,10 @@ def launch_virtual_tally(auth_event): callback_url, json=reproducible_json_dumps({}), headers={ - 'Authorization': genhmac( + 'Authorization': generate_access_token_hmac( settings.SHARED_SECRET, - "1:AuthEvent:%s:tally" % auth_event.id + "1:AuthEvent:%s:tally" % auth_event.id, + auth_event.get_refresh_token_duration_secs() ), 'Content-type': 'application/json' } @@ -545,9 +547,10 @@ def update_ballot_boxes_config(auth_event_id): callback_url, json=ballot_boxes_config, headers={ - 'Authorization': genhmac( + 'Authorization': generate_access_token_hmac( settings.SHARED_SECRET, - "1:AuthEvent:%s:update-ballot-boxes-results-config" % auth_event_id + "1:AuthEvent:%s:update-ballot-boxes-results-config" % auth_event_id, + auth_event_id.get_refresh_token_duration_secs() ), 'Content-type': 'application/json' } @@ -618,9 +621,10 @@ def calculate_results_task(user_id, event_id_list): callback_url, data=config, headers={ - 'Authorization': genhmac( + 'Authorization': generate_access_token_hmac( settings.SHARED_SECRET, - "1:AuthEvent:%s:calculate-results" % auth_event_id + "1:AuthEvent:%s:calculate-results" % auth_event_id, + auth_event.get_refresh_token_duration_secs() ), 'Content-type': 'application/json' } @@ -732,9 +736,10 @@ def publish_results_task(user_id, auth_event_id, visit_children, parent_auth_eve callback_url, json=data, headers={ - 'Authorization': genhmac( + 'Authorization': generate_access_token_hmac( settings.SHARED_SECRET, - "1:AuthEvent:%s:publish-results" % auth_event_id + "1:AuthEvent:%s:publish-results" % auth_event_id, + auth_event.get_refresh_token_duration_secs() ), 'Content-type': 'application/json' } @@ -840,9 +845,10 @@ def unpublish_results_task(user_id, auth_event_id, parent_auth_event_id=None): callback_url, json=data, headers={ - 'Authorization': genhmac( + 'Authorization': generate_access_token_hmac( settings.SHARED_SECRET, - "1:AuthEvent:%s:publish-results" % auth_event_id + "1:AuthEvent:%s:publish-results" % auth_event_id, + auth_event.get_refresh_token_duration_secs() ), 'Content-type': 'application/json' } @@ -955,9 +961,10 @@ def set_public_candidates_task( callback_url, json=data, headers={ - 'Authorization': genhmac( + 'Authorization': generate_access_token_hmac( settings.SHARED_SECRET, - "1:AuthEvent:%s:set-public-candidates" % auth_event_id + "1:AuthEvent:%s:set-public-candidates" % auth_event_id, + auth_event.get_refresh_token_duration_secs() ), 'Content-type': 'application/json' } @@ -1094,9 +1101,10 @@ def get_parent_event(parent_event_id, auth_event): callback_url, json=data, headers={ - 'Authorization': genhmac( + 'Authorization': generate_access_token_hmac( settings.SHARED_SECRET, - f"1:AuthEvent:{current_event_id}:{action_name}" + f"1:AuthEvent:{current_event_id}:{action_name}", + current_event.get_refresh_token_duration_secs() ), 'Content-type': 'application/json' } diff --git a/iam/api/test_data.py b/iam/api/test_data.py index 96cc4913..53b44a3b 100644 --- a/iam/api/test_data.py +++ b/iam/api/test_data.py @@ -1554,7 +1554,7 @@ def generate_auth_event_and_voter_credentials(auth_method): authentication method. ''' from api.models import AuthEvent - from authmethods.utils import genhmac + from authmethods.utils import generate_access_token_hmac from authmethods.models import Code auth_event = None voter = None @@ -1834,14 +1834,15 @@ def generate_auth_event_and_voter_credentials(auth_method): voter.userdata.save() credentials = { - 'auth-token': genhmac( + 'auth-token': generate_access_token_hmac( key=settings.SHARED_SECRET, msg=':'.join([ voter.userdata.metadata['user_id'], 'AuthEvent', str(auth_event.id), 'vote' - ]) + ]), + validity=auth_event.refresh_token_duration_secs ) } else: diff --git a/iam/api/tests.py b/iam/api/tests.py index 65b4fb23..0d76db9b 100644 --- a/iam/api/tests.py +++ b/iam/api/tests.py @@ -3101,14 +3101,16 @@ def setUp(self): self.u = u.userdata self.uid = u.id - def genhmac(self, key, msg): + def generate_access_token_hmac(self, key, msg): import hmac if not key or not msg: return timestamp = int(timezone.now().timestamp()) - msg = "%s:%s" % (msg, str(timestamp)) + validity = 120 + expiry_timestamp = timestamp + validity + msg = "%s:%s:%s:%s" % (msg, str(expiry_timestamp), "timeout-token", str(timestamp)) h = hmac.new(key, msg.encode('utf-8'), "sha256") return 'khmac:///sha-256;' + h.hexdigest() + '/' + msg @@ -3117,7 +3119,7 @@ def genhmac(self, key, msg): def test_callback(self): c = JClient() timed_auth = "test:AuthEvent:%d:Callback" % self.aeid - hmac = self.genhmac(settings.SHARED_SECRET, timed_auth) + hmac = self.generate_access_token_hmac(settings.SHARED_SECRET, timed_auth) c.set_auth_token(hmac) response = c.post('/api/auth-event/%d/callback/' % self.aeid, {}) self.assertEqual(response.status_code, 200) @@ -3275,11 +3277,13 @@ class TestRevotes(TestCase): def setUpTestData(): flush_db_load_fixture() - def genhmac(self, key, msg): + def generate_access_token_hmac(self, key, msg): import hmac import datetime timestamp = int(timezone.now().timestamp()) - msg = "%s:%s" % (msg, str(timestamp)) + validity = 120 + expiry_timestamp = timestamp + validity + msg = "%s:%s:%s:%s" % (msg, str(expiry_timestamp), "timeout-token", str(timestamp)) h = hmac.new(key, msg.encode('utf-8'), "sha256") return 'khmac:///sha-256;' + h.hexdigest() + '/' + msg @@ -3348,7 +3352,7 @@ def test_check_1_2_revotes(self): self.assertEqual(response.status_code, 200) response = c.authenticate(self.aeid, test_data.auth_email_default1) self.assertEqual(response.status_code, 200) - auth_token = self.genhmac(settings.SHARED_SECRET, "%s:AuthEvent:%d:RegisterSuccessfulLogin" % (cuser.username, self.aeid)) + auth_token = self.generate_access_token_hmac(settings.SHARED_SECRET, "%s:AuthEvent:%d:RegisterSuccessfulLogin" % (cuser.username, self.aeid)) c.set_auth_token(auth_token) response = c.post('/api/auth-event/%d/successful_login/%s' % (self.aeid, cuser.username), {}) self.assertEqual(response.status_code, 200) @@ -3364,7 +3368,7 @@ def test_check_1_2_revotes(self): self.assertEqual(response.status_code, 200) response = c.authenticate(self.aeid, test_data.auth_email_default1) self.assertEqual(response.status_code, 200) - auth_token = self.genhmac(settings.SHARED_SECRET, "%s:AuthEvent:%d:RegisterSuccessfulLogin" % (cuser.username, self.aeid)) + auth_token = self.generate_access_token_hmac(settings.SHARED_SECRET, "%s:AuthEvent:%d:RegisterSuccessfulLogin" % (cuser.username, self.aeid)) c.set_auth_token(auth_token) response = c.post('/api/auth-event/%d/successful_login/%s' % (self.aeid, cuser.username), {}) self.assertEqual(response.status_code, 200) @@ -3394,7 +3398,7 @@ def test_check_50_revotes_max(self): for i in range(0, 50): response = c.authenticate(self.aeid, test_data.auth_email_default1) self.assertEqual(response.status_code, 200) - auth_token = self.genhmac(settings.SHARED_SECRET, "%s:AuthEvent:%d:RegisterSuccessfulLogin" % (cuser.username, self.aeid)) + auth_token = self.generate_access_token_hmac(settings.SHARED_SECRET, "%s:AuthEvent:%d:RegisterSuccessfulLogin" % (cuser.username, self.aeid)) c.set_auth_token(auth_token) response = c.post('/api/auth-event/%d/successful_login/%s' % (self.aeid, cuser.username), {}) diff --git a/iam/api/views.py b/iam/api/views.py index 019c42bf..e0a10f6f 100644 --- a/iam/api/views.py +++ b/iam/api/views.py @@ -57,7 +57,7 @@ update_alt_methods_config, check_alt_auth_methods, check_admin_fields, - genhmac, + generate_access_token_hmac, HMACToken, json_response, paginate, @@ -670,7 +670,6 @@ def post(self, request, pk): ) authenticate = Authenticate.as_view() - class AuthenticateOtl(View): ''' Authenticate into the iam ''' @@ -791,12 +790,12 @@ def get(self, request, pk): data = {} if u and error is None: - data = { - 'auth-token': genhmac(settings.SHARED_SECRET, u.username) - } + data = {} auth_event = get_object_or_404(AuthEvent, pk=pk) req = {} auth_data = return_auth_data('Ping', req, request, u, auth_event) + if 'auth-token' in auth_data: + data['auth-token'] = auth_data['auth-token'] if 'vote-permission-token' in auth_data: data['vote-permission-token'] = auth_data['vote-permission-token'] if 'vote-children-info' in auth_data: @@ -1236,8 +1235,9 @@ def post(self, request): error_codename=ErrorCodes.BAD_REQUEST) msg = ':'.join((request.user.username, object_type, str(obj_id), filtered_perms)) + auth_event = request.user.userdata.event - data['permission-token'] = genhmac(settings.SHARED_SECRET, msg) + data['permission-token'] = generate_access_token_hmac(settings.SHARED_SECRET, msg, auth_event.get_access_token_duration_secs()) return json_response(data) getperms = login_required(GetPerms.as_view()) @@ -1908,7 +1908,7 @@ def post(request, pk=None): action.save() - data = {'status': 'ok', 'id': ae.pk, 'perm': acl.get_hmac()} + data = {'status': 'ok', 'id': ae.pk, 'perm': acl.get_hmac(ae.get_refresh_token_duration_secs())} return json_response(data) def get(self, request, pk=None): diff --git a/iam/authmethods/m_dnie.py b/iam/authmethods/m_dnie.py index 2e328d39..59004db6 100644 --- a/iam/authmethods/m_dnie.py +++ b/iam/authmethods/m_dnie.py @@ -92,7 +92,7 @@ def dnie_auth(request, authid): # u = ud.user #msg = ':'.join((u.username, "AuthEvent", ae.id, "vote")) - #khmac = genhmac(settings.SHARED_SECRET, msg) + #khmac = generate_access_token_hmac(settings.SHARED_SECRET, msg, ae.refresh_token_duration_secs) #head, path = khmac.split(";")[1] #array = path.split("/") #hash, msg = array[0], array[1] diff --git a/iam/authmethods/m_smart_link.py b/iam/authmethods/m_smart_link.py index 37cc49c5..aff43a0e 100644 --- a/iam/authmethods/m_smart_link.py +++ b/iam/authmethods/m_smart_link.py @@ -372,7 +372,7 @@ def authenticate(self, auth_event, request): error_codename=SmartLinkErrorCodes.INVALID_PERMISSION ) - if not hmac_token.check_expiration(settings.TIMEOUT): + if not hmac_token.check_expiration(settings.SMARTLINK_TIMEOUT): return self.error( SmartLinkErrorCodes.EXPIRED_AUTH_TOKEN, auth_event=auth_event, @@ -395,7 +395,7 @@ def authenticate(self, auth_event, request): verified = verifyhmac( key=shared_secret, msg=hmac_token.msg, - seconds=settings.TIMEOUT, + seconds=settings.SMARTLINK_TIMEOUT, at=hmac_token ) diff --git a/iam/authmethods/tests.py b/iam/authmethods/tests.py index e83f7154..d58ae5a0 100644 --- a/iam/authmethods/tests.py +++ b/iam/authmethods/tests.py @@ -28,7 +28,7 @@ from .m_email import Email from .m_sms import Sms from .models import Message, Code -from utils import genhmac, ErrorCodes +from utils import generate_access_token_hmac, ErrorCodes class AuthMethodTestCase(TestCase): @@ -262,9 +262,10 @@ def test_authenticate_valid_auth_token(self): 'vote' ]) data = { - 'auth-token': genhmac( + 'auth-token': generate_access_token_hmac( key=settings.SHARED_SECRET, - msg=message + msg=message, + validity=self.auth_event.refresh_token_duration_secs ) } response = c.authenticate(self.auth_event.id, data) @@ -290,9 +291,10 @@ def test_authenticate_valid_auth_token_tilde(self): 'vote' ]) data = { - 'auth-token': genhmac( + 'auth-token': generate_access_token_hmac( key=settings.SHARED_SECRET, - msg=message + msg=message, + validity=self.auth_event.refresh_token_duration_secs ) } response = c.authenticate(self.auth_event.id, data) diff --git a/iam/authmethods/utils.py b/iam/authmethods/utils.py index fd93c1f3..3a3f0ae1 100644 --- a/iam/authmethods/utils.py +++ b/iam/authmethods/utils.py @@ -38,7 +38,7 @@ get_client_ip, constant_time_compare, permission_required, - genhmac, + generate_access_token_hmac, stack_trace_str, generate_code, send_codes, @@ -1579,6 +1579,7 @@ def return_auth_data(logger_name, req_json, request, user, auth_event=None): user_logged_in.send(sender=user.__class__, request=request, user=user) user.save() + # this is the data that will be returned data = {'status': 'ok'} @@ -1588,14 +1589,18 @@ def return_auth_data(logger_name, req_json, request, user, auth_event=None): username = user.username.decode('utf-8') data['username'] = username - # generate the user auth-token - data['auth-token'] = genhmac(settings.SHARED_SECRET, user.username) if auth_event is None: auth_event = user.userdata.event + is_admin = user.userdata.event_id == settings.ADMIN_AUTH_ID + + # generate the user auth-token + if 'Ping' != logger_name or is_admin: + data['auth-token'] = generate_access_token_hmac(settings.SHARED_SECRET, user.username, auth_event.get_refresh_token_duration_secs()) + if auth_event.children_election_info is None: msg = ':'.join((user.username, 'AuthEvent', str(auth_event.id), 'vote')) - data['vote-permission-token'] = genhmac(settings.SHARED_SECRET, msg) + data['vote-permission-token'] = generate_access_token_hmac(settings.SHARED_SECRET, msg, auth_event.get_access_token_duration_secs()) else: def get_child_info(event_id): auth_event = AuthEvent.objects.get(pk=event_id) @@ -1618,13 +1623,13 @@ def get_child_info(event_id): ): msg = ':'.join((user.username, 'AuthEvent', str(event_id), 'vote')) - auth_token = genhmac(settings.SHARED_SECRET, msg) + access_token = generate_access_token_hmac(settings.SHARED_SECRET, msg, auth_event.get_access_token_duration_secs()) else: - auth_token = None + access_token = None return { 'auth-event-id': event_id, - 'vote-permission-token': auth_token, + 'vote-permission-token': access_token, 'num-successful-logins-allowed': max_num_successful_logins, 'num-successful-logins': num_successful_logins } diff --git a/iam/iam/settings.py b/iam/iam/settings.py index e4efc438..c9ce47e1 100644 --- a/iam/iam/settings.py +++ b/iam/iam/settings.py @@ -66,10 +66,16 @@ class CeleryConfig: ADMIN_AUTH_ID = 1 -TIMEOUT = 300 +SMARTLINK_TIMEOUT = 90 + +ACCESS_TIMEOUT = 60 + +REFRESH_TIMEOUT = 600 ADMIN_TIMEOUT = 3000 +REFRESH_TIMEOUT = 600 + ALLOW_ADMIN_AUTH_REGISTRATION = False ALLOW_DEREGISTER = True diff --git a/iam/iam/test_settings.py b/iam/iam/test_settings.py index 0562b018..1ae05568 100644 --- a/iam/iam/test_settings.py +++ b/iam/iam/test_settings.py @@ -83,10 +83,16 @@ class CeleryConfig: ALLOWED_HOSTS = [] -TIMEOUT = 300 +SMARTLINK_TIMEOUT = 90 + +ACCESS_TIMEOUT = 60 + +REFRESH_TIMEOUT = 600 ADMIN_TIMEOUT = 3000 +REFRESH_TIMEOUT = 600 + ADMIN_AUTH_ID = 1 ALLOW_ADMIN_AUTH_REGISTRATION = False diff --git a/iam/utils.py b/iam/utils.py index 82fd46c2..909e505f 100644 --- a/iam/utils.py +++ b/iam/utils.py @@ -53,7 +53,7 @@ RE_INT = re.compile('^\d+$') RE_BOOL = re.compile('^(true|false)$') LOGGER = getLogger('iam.notify') - +TIMEOUT_TOKEN_STR = 'timeout-token' def stack_trace_str(): frame = inspect.currentframe() @@ -196,6 +196,13 @@ def genhmac(key, msg): h = hmac.new(key, msg.encode('utf-8'), "sha256") return 'khmac:///sha-256;' + h.hexdigest() + '/' + msg +def generate_access_token_hmac(key, msg, validity): + timestamp = int(timezone.now().timestamp()) + expiry_timestamp = timestamp + validity + msg = "%s:%s:%s:%s" % (msg, str(expiry_timestamp), TIMEOUT_TOKEN_STR, str(timestamp)) + + h = hmac.new(key, msg.encode('utf-8'), "sha256") + return 'khmac:///sha-256;' + h.hexdigest() + '/' + msg def verifyhmac(key, msg, seconds=300, at=None): if at is None: @@ -206,6 +213,12 @@ def verifyhmac(key, msg, seconds=300, at=None): valid = valid and at.check_expiration(seconds) return valid +# khmac:///sha-256;2a03ad3ecee88f645833a1a0eb99a7e43a8599a473997cb2f606872e33b1928a/admin:1719446123 +# data = 2a03ad3ecee88f645833a1a0eb99a7e43a8599a473997cb2f606872e33b1928a/admin:1719446123 +# hash = 2a03ad3ecee88f645833a1a0eb99a7e43a8599a473997cb2f606872e33b1928a +# msg = admin:1719446123 +# msg_split = ['admin' , '1719446123'] +# timestamp = '1719446123' class HMACToken: def __init__(self, token): @@ -217,22 +230,34 @@ def __init__(self, token): self.hash, self.msg = data.split('/', 1) msg_split = self.msg.split(':') self.timestamp = msg_split[-1] - if len(msg_split) >= 5: - self.userid = ':'.join(msg_split[0:-4]) - self.other_values = msg_split[-4:-1] + + has_expiry = len(msg_split) >= 4 and TIMEOUT_TOKEN_STR == msg_split[-2] + self.expiry_timestamp = msg_split[-3] if has_expiry else False + + if len(msg_split) >= 7: + self.userid = ':'.join(msg_split[0:-6]) + self.other_values = msg_split[-6:-3] else: self.userid = msg_split[0] - self.other_values = msg_split[1:-1] + self.other_values = msg_split[1:-3] def check_expiration(self, seconds=300): - t = self.timestamp - n = timezone.now() - d = datetime.datetime.fromtimestamp( - int(t), - tz=timezone.get_current_timezone() - ) - d = d + datetime.timedelta(seconds=seconds) - return d > n + ''' + returns true iff the token hasn't expired + ''' + now = timezone.now() + if False != self.expiry_timestamp: + expiry_date = datetime.datetime.fromtimestamp( + int(self.expiry_timestamp), + tz=timezone.get_current_timezone() + ) + else: + expiry_date = datetime.datetime.fromtimestamp( + int(self.timestamp), + tz=timezone.get_current_timezone() + ) + expiry_date = expiry_date + datetime.timedelta(seconds=seconds) + return expiry_date > now def get_userid(self): '''