|
@@ -1,9 +1,31 @@
|
|
|
|
+import base64
|
|
from hashlib import sha256
|
|
from hashlib import sha256
|
|
|
|
+from time import time
|
|
|
|
|
|
from django.conf import settings
|
|
from django.conf import settings
|
|
|
|
|
|
|
|
|
|
|
|
+"""
|
|
|
|
+Token creation
|
|
|
|
+
|
|
|
|
+Token is base encoded string containing three values:
|
|
|
|
+
|
|
|
|
+- days since unix epoch (so we can validate token expiration)
|
|
|
|
+- hash unique for current state of user model
|
|
|
|
+- token checksum for discovering manipulations
|
|
|
|
+"""
|
|
def make(user, token_type):
|
|
def make(user, token_type):
|
|
|
|
+ user_hash = make_hash(user, token_type)
|
|
|
|
+ creation_day = days_since_epoch()
|
|
|
|
+
|
|
|
|
+ obfuscated = base64.b64encode('%s%s' % (user_hash, creation_day))
|
|
|
|
+ obfuscated = obfuscated.rstrip('=')
|
|
|
|
+ checksum = make_checksum(obfuscated)
|
|
|
|
+
|
|
|
|
+ return '%s%s' % (checksum, obfuscated)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def make_hash(user, token_type):
|
|
seeds = (
|
|
seeds = (
|
|
user.pk,
|
|
user.pk,
|
|
user.email,
|
|
user.email,
|
|
@@ -13,11 +35,32 @@ def make(user, token_type):
|
|
settings.SECRET_KEY,
|
|
settings.SECRET_KEY,
|
|
)
|
|
)
|
|
|
|
|
|
- return sha256('+'.join([unicode(s) for s in seeds])).hexdigest()[:12]
|
|
|
|
|
|
+ return sha256('+'.join([unicode(s) for s in seeds])).hexdigest()[:8]
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def days_since_epoch():
|
|
|
|
+ return int(time() / (25 * 3600))
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def make_checksum(obfuscated):
|
|
|
|
+ return sha256('%s:%s' % (settings.SECRET_KEY, obfuscated)).hexdigest()[:8]
|
|
|
|
|
|
|
|
|
|
def is_valid(user, token_type, token):
|
|
def is_valid(user, token_type, token):
|
|
- return token == make(user, token_type)
|
|
|
|
|
|
+ checksum = token[:8]
|
|
|
|
+ obfuscated = token[8:]
|
|
|
|
+
|
|
|
|
+ if checksum != make_checksum(obfuscated):
|
|
|
|
+ return False
|
|
|
|
+
|
|
|
|
+ unobfuscated = base64.b64decode(obfuscated + '=' * (-len(obfuscated) % 4))
|
|
|
|
+ user_hash = unobfuscated[:8]
|
|
|
|
+
|
|
|
|
+ if user_hash != make_hash(user, token_type):
|
|
|
|
+ return False
|
|
|
|
+
|
|
|
|
+ creation_day = int(unobfuscated[8:])
|
|
|
|
+ return creation_day + 14 >= days_since_epoch()
|
|
|
|
|
|
|
|
|
|
"""
|
|
"""
|