def test_tokens_differ_for_different_master_secrets(self): manager1 = tokenlib.TokenManager(secret="one") manager2 = tokenlib.TokenManager(secret="two") token1 = manager1.make_token({"test": "data"}) token2 = manager2.make_token({"test": "data"}) self.assertNotEquals(token1, token2) self.assertNotEquals(manager1.get_token_secret(token1), manager2.get_token_secret(token2)) self.assertRaises(ValueError, manager1.parse_token, token2) self.assertRaises(ValueError, manager2.parse_token, token1)
def test_tokens_differ_for_different_master_secrets(self): manager1 = tokenlib.TokenManager(secret="one") manager2 = tokenlib.TokenManager(secret="two") token1 = manager1.make_token({"test": "data"}) token2 = manager2.make_token({"test": "data"}) self.assertNotEquals(token1, token2) self.assertNotEquals(manager1.get_derived_secret(token1), manager2.get_derived_secret(token2)) with self.assertRaises(errors.InvalidSignatureError): manager1.parse_token(token2) with self.assertRaises(errors.InvalidSignatureError): manager2.parse_token(token1)
def test_token_validation(self): manager = tokenlib.TokenManager(timeout=0.2) token = manager.make_token({"hello": "world"}) token_bytes = decode_token_bytes(token) # Proper token == valid. data = manager.parse_token(token) self.assertEquals(data["hello"], "world") # Badly-encoded bytes == not valid. bad_token = "@" + token[1:] with self.assertRaises(errors.MalformedTokenError): manager.parse_token(bad_token) # Bad signature == not valid. bad_token = encode_token_bytes(b"X" * 50) with self.assertRaises(errors.InvalidSignatureError): manager.parse_token(bad_token) bad_token_bytes = token_bytes[:-1] bad_token_bytes += b"X" if token_bytes[-1] == b"Z" else b"Z" bad_token = encode_token_bytes(bad_token_bytes) with self.assertRaises(errors.InvalidSignatureError): manager.parse_token(bad_token) # Modified payload == not valid. bad_token = encode_token_bytes(b"admin" + token_bytes[6:]) with self.assertRaises(errors.InvalidSignatureError): manager.parse_token(bad_token) # Expired token == not valid. time.sleep(0.2) with self.assertRaises(errors.ExpiredTokenError): manager.parse_token(token)
def test_get_token_secret_errors_out_for_malformed_tokens(self): manager = tokenlib.TokenManager() bad_token = b64encode("{}" + ("X" * manager.hashmod_digest_size)) self.assertRaises(ValueError, manager.get_token_secret, bad_token) bad_token = b64encode("42" + ("X" * manager.hashmod_digest_size)) self.assertRaises(ValueError, manager.get_token_secret, bad_token) bad_token = b64encode("NOTJSON" + ("X" * manager.hashmod_digest_size)) self.assertRaises(ValueError, manager.get_token_secret, bad_token)
def test_token_secrets_differ_for_each_token(self): manager = tokenlib.TokenManager() token1 = manager.make_token({"test": "one"}) token2 = manager.make_token({"test": "two"}) self.assertEquals(manager.get_token_secret(token1), manager.get_token_secret(token1)) self.assertNotEquals(manager.get_token_secret(token1), manager.get_token_secret(token2))
def __init__(self, secret): """ """ self.tman = tokenlib.TokenManager( secret=secret, # I want non expiring tokens for now. A hack is to set this to # a value higher then 'now' used when verifing. timeout=10, # Set to the strongest has available in py2.7 which we should # review every so often. hashmod=hashlib.sha512, )
def test_get_derived_secret_errors_out_for_malformed_tokens(self): manager = tokenlib.TokenManager() digest_size = manager.hashmod_digest_size bad_token = encode_token_bytes(b"{}" + (b"X" * digest_size)) with self.assertRaises(errors.MalformedTokenError): manager.get_derived_secret(bad_token) bad_token = encode_token_bytes(b"42" + (b"X" * digest_size)) with self.assertRaises(errors.MalformedTokenError): manager.get_derived_secret(bad_token) bad_token = encode_token_bytes(b"NOTJSON" + (b"X" * digest_size)) with self.assertRaises(errors.MalformedTokenError): manager.get_derived_secret(bad_token)
def decode_hawk_id(self, request, tokenid): """Decode a Hawk token id into its userid and secret key. This method determines the appropriate secrets to use for the given request, then passes them on to tokenlib to handle the given Hawk token. If the id is invalid then ValueError will be raised. Unlike the superclass method, this implementation allows expired tokens to be used up to a configurable timeout. The effective userid for expired tokens is changed to be "expired:<uid>". """ now = time.time() node_name = self._get_node_name(request) # There might be multiple secrets in use, # so try each until we find one that works. secrets = self._get_token_secrets(node_name) for secret in secrets: try: tm = tokenlib.TokenManager(secret=secret) # Check for a proper valid signature first. # If that failed because of an expired token, check if # it falls within the allowable expired-token window. try: data = tm.parse_token(tokenid, now=now) except tokenlib.errors.ExpiredTokenError: recently = now - self.expired_token_timeout data = tm.parse_token(tokenid, now=recently) data["uid"] = "expired:%d" % (data["uid"], ) except ValueError: # Token validation failed, move on to the next secret. continue else: # Token validation succeeded, quit the loop. break else: # The token failed to validate using any secret. log_cef("Authentication Failed: invalid hawk id", 5, request.environ, request.registry.settings, "", signature=AUTH_FAILURE) raise ValueError("invalid Hawk id") # Sanity-check the contained data. # Any errors raise ValueError, triggering auth failure. try: userid = data["uid"] token_node_name = data["node"] except KeyError, e: msg = "missing value in token data: %s" raise ValueError(msg % (e, ))
def test_token_validation(self): manager = tokenlib.TokenManager(timeout=0.2) token = manager.make_token({"hello": "world"}) # Proper token == valid. data = manager.parse_token(token) self.assertEquals(data["hello"], "world") # Bad signature == not valid. bad_token = token[:-1] + ("X" if token[-1] == "Z" else "Z") self.assertRaises(ValueError, manager.parse_token, bad_token) bad_token = ("X" * 50).encode("base64").strip() self.assertRaises(ValueError, manager.parse_token, bad_token) # Modified payload == not valid. bad_token = "admin" + token[6:] self.assertRaises(ValueError, manager.parse_token, bad_token) # Expired token == not valid. time.sleep(0.2) self.assertRaises(ValueError, manager.parse_token, token)
def decode_hawk_id(self, request, tokenid): """Decode a Hawk token id into its userid and secret key. This method determines the appropriate secrets to use for the given request, then passes them on to tokenlib to handle the given Hawk token. If the id is invalid then ValueError will be raised. Unlike the superclass method, this implementation allows expired tokens to be used up to a configurable timeout. The effective userid for expired tokens is changed to be "expired:<uid>". """ now = time.time() node_name = self._get_node_name(request) # There might be multiple secrets in use, # so try each until we find one that works. secrets = self._get_token_secrets(node_name) for secret in secrets: try: tm = tokenlib.TokenManager(secret=secret) # Check for a proper valid signature first. # If that failed because of an expired token, check if # it falls within the allowable expired-token window. try: data = self._parse_token(tm, tokenid, now) userid = data["uid"] except tokenlib.errors.ExpiredTokenError: recently = now - self.expired_token_timeout data = self._parse_token(tm, tokenid, recently) # We replace the uid with a special string to ensure that # calling code doesn't accidentally treat the token as # valid. If it wants to use the expired uid, it will have # to explicitly dig it back out from `request.user`. data["expired_uid"] = data["uid"] userid = data["uid"] = "expired:%d" % (data["uid"],) except tokenlib.errors.InvalidSignatureError, e: # Token signature check failed, try the next secret. continue except TypeError, e: # Something went wrong when validating the contained data. raise ValueError(str(e))
import auth app = Flask(__name__) # using decouple to get the configuration from .env app.config.update( dict(DEBUG=config('DEBUG', False), SECRET_KEY=config('SECRET_KEY'), EMAIL_HOST=config('EMAIL_HOST', ''), EMAIL_PORT=config('EMAIL_PORT', ''), EMAIL_HOST_PASSWORD=config('EMAIL_HOST_PASSWORD', ''), EMAIL_HOST_USER=config('EMAIL_HOST_USER', ''), EMAIL_USE_SSL=config('EMAIL_USE_SSL', ''), TOKEN_MANAGER=tokenlib.TokenManager( secret=config('SECRET_KEY'), timeout=24 * 3600, ))) token_manager = app.config.get('TOKEN_MANAGER') @app.route('/') def home(): return render_template('home.html') @app.route('/signup', methods=[ 'GET', 'POST', ]) def signup():
} } dictConfig(LOGGING) # Email configuration EMAIL_HOST = config('EMAIL_HOST', default='localhost') EMAIL_PORT = config('EMAIL_PORT', default=25, cast=int) EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD', default='') EMAIL_HOST_USER = config('EMAIL_HOST_USER', default='') EMAIL_USE_TLS = config('EMAIL_USE_TLS', default=False, cast=bool) # AUTH_USER_MODEL = 'hotel_example.User' # Auth settings TOKEN_MANAGER = tokenlib.TokenManager( secret=config('EMAIL_PORT', cast=str, default='I_LIKE_UNICORNS!')) HASH_ROUNDS = 2000 HASH_SALT_SIZE = 16 # MongoDB _MONGODB_USER = config('MONGODB_USER', cast=str, default=None) _MONGODB_PASSWD = config('MONGODB_PASSWORD', cast=str, default=None) _MONGODB_HOST = config('MONGODB_HOST', cast=str, default=None) _MONGODB_NAME = config('MONGODB_NAME', cast=str, default=None) if '' not in (_MONGODB_USER, _MONGODB_PASSWD, _MONGODB_HOST): _MONGODB_DATABASE_HOST = 'mongodb://{}:{}@{}/{}'.format( _MONGODB_USER, _MONGODB_PASSWD, _MONGODB_HOST, _MONGODB_NAME) else: _MONGODB_DATABASE_HOST = 'mongodb://localhost/{}'.format(_MONGODB_NAME) mongoengine.connect(_MONGODB_NAME, host=_MONGODB_DATABASE_HOST)
def test_loading_hashmod_by_string_name(self): manager = tokenlib.TokenManager(hashmod="md5") self.assertTrue(manager.hashmod is hashlib.md5)
# -*- coding: utf-8 -*- import tokenlib import time from rest_framework import authentication from rest_framework import exceptions from django.utils import timezone from constants import constants from constants import error_constants token_manager = tokenlib.TokenManager(secret=constants.SECRET_KEY, timeout=constants.expire_time) def create_token(user_name): data = {'user_name': user_name} token = token_manager.make_token(data) return token class SystemAuthentication(authentication.BaseAuthentication): def authenticate(self, request): try: req_token = request.META['HTTP_AUTHORIZATION'] except: raise exceptions.AuthenticationFailed( error_constants.ERR_TOKEN_ERROR) # 判断 get 还是 post if request.method == 'POST': user_name = request.POST.get('userName', '0') elif request.method == 'PUT':
def test_master_secret_can_be_unicode_string(self): manager = tokenlib.TokenManager(secret=b"one".decode("ascii")) token = manager.make_token({"test": "data"}) self.assertEquals(manager.parse_token(token)["test"], "data")
def decode_hawk_id(self, request, tokenid): """Decode a Hawk token id into its userid and secret key. This method determines the appropriate secrets to use for the given request, then passes them on to tokenlib to handle the given Hawk token. If the id is invalid then ValueError will be raised. Unlike the superclass method, this implementation allows expired tokens to be used up to a configurable timeout. The effective userid for expired tokens is changed to be "expired:<uid>". """ now = time.time() node_name = self._get_node_name(request) # There might be multiple secrets in use, # so try each until we find one that works. secrets = self._get_token_secrets(node_name) for secret in secrets: try: tm = tokenlib.TokenManager(secret=secret) # Check for a proper valid signature first. # If that failed because of an expired token, check if # it falls within the allowable expired-token window. try: data = self._parse_token(tm, tokenid, now) userid = data["uid"] except tokenlib.errors.ExpiredTokenError: recently = now - self.expired_token_timeout data = self._parse_token(tm, tokenid, recently) # We replace the uid with a special string to ensure that # calling code doesn't accidentally treat the token as # valid. If it wants to use the expired uid, it will have # to explicitly dig it back out from `request.user`. data["expired_uid"] = data["uid"] userid = data["uid"] = "expired:%d" % (data["uid"],) except tokenlib.errors.InvalidSignatureError: # Token signature check failed, try the next secret. continue except TypeError as e: # Something went wrong when validating the contained data. raise ValueError(str(e)) else: # Token signature check succeeded, quit the loop. break else: # The token failed to validate using any secret. print("warn Authentication Failed: invalid hawk id") raise ValueError("invalid Hawk id") # Let the app access all user data from the token. request.user.update(data) request.metrics["metrics_uid"] = data.get("hashed_fxa_uid") request.metrics["metrics_device_id"] = data.get("hashed_device_id") # Sanity-check that we're on the right node. if data["node"] != node_name: msg = "incorrect node for this token: %s" raise ValueError(msg % (data["node"],)) # Calculate the matching request-signing secret. key = tokenlib.get_derived_secret(tokenid, secret=secret) return userid, key