def test_asymmetric_jwe_token_plugin(self): private_key = jwt.JWK() public_key = jwt.JWK() private_key_data = open("./tests/fixtures/private.pem", "rb").read() public_key_data = open("./tests/fixtures/public.pem", "rb").read() private_key.import_from_pem(private_key_data) public_key.import_from_pem(public_key_data) jwt_token = jwt.JWT({"alg": "RS256"}, { 'host': "remote_host", 'port': "remote_port" }) jwt_token.make_signed_token(private_key) jwe_token = jwt.JWT(header={ "alg": "RSA1_5", "enc": "A256CBC-HS512" }, claims=jwt_token.serialize()) jwe_token.make_encrypted_token(public_key) self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format( jwt_token=jwe_token.serialize()) patcher = patch( 'websockify.websocketproxy.ProxyRequestHandler.send_auth_error' ).start() self.handler.server.token_plugin = token_plugins.JWTTokenApi( "./tests/fixtures/private.pem") self.handler.validate_connection() self.assertEqual(self.handler.server.target_host, "remote_host") self.assertEqual(self.handler.server.target_port, "remote_port")
def test_asymmetric_jwe_token_plugin(self): plugin = JWTTokenApi("./tests/fixtures/private.pem") private_key = jwt.JWK() public_key = jwt.JWK() private_key_data = open("./tests/fixtures/private.pem", "rb").read() public_key_data = open("./tests/fixtures/public.pem", "rb").read() private_key.import_from_pem(private_key_data) public_key.import_from_pem(public_key_data) jwt_token = jwt.JWT({"alg": "RS256"}, { 'host': "remote_host", 'port': "remote_port" }) jwt_token.make_signed_token(private_key) jwe_token = jwt.JWT(header={ "alg": "RSA-OAEP", "enc": "A256CBC-HS512" }, claims=jwt_token.serialize()) jwe_token.make_encrypted_token(public_key) result = plugin.lookup(jwt_token.serialize()) self.assertIsNotNone(result) self.assertEqual(result[0], "remote_host") self.assertEqual(result[1], "remote_port")
def lookup(self, token): try: from jwcrypto import jwt import json key = jwt.JWK() try: with open(self.source, 'rb') as key_file: key_data = key_file.read() except Exception as e: print("Error loading key file: %s" % str(e), file=sys.stderr) return None try: key.import_from_pem(key_data) except: try: key.import_key(k=key_data.decode('utf-8'), kty='oct') except: print('Failed to correctly parse key data!', file=sys.stderr) return None try: token = jwt.JWT(key=key, jwt=token) parsed_header = json.loads(token.header) if 'enc' in parsed_header: # Token is encrypted, so we need to decrypt by passing the claims to a new instance token = jwt.JWT(key=key, jwt=token.claims) parsed = json.loads(token.claims) if 'nbf' in parsed: # Not Before is present, so we need to check it if time.time() < parsed['nbf']: print('Token can not be used yet!', file=sys.stderr) return None if 'exp' in parsed: # Expiration time is present, so we need to check it if time.time() > parsed['exp']: print('Token has expired!', file=sys.stderr) return None return (parsed['host'], parsed['port']) except Exception as e: print("Failed to parse token: %s" % str(e), file=sys.stderr) return None except ImportError as e: print( "package jwcrypto not found, are you sure you've installed it correctly?", file=sys.stderr) return None
def test_asymmetric_jws_token_plugin_with_illigal_key_exception(self): plugin = JWTTokenApi("wrong.pub") key = jwt.JWK() private_key = open("./tests/fixtures/private.pem", "rb").read() key.import_from_pem(private_key) jwt_token = jwt.JWT({"alg": "RS256"}, {'host': "remote_host", 'port': "remote_port"}) jwt_token.make_signed_token(key) result = plugin.lookup(jwt_token.serialize()) self.assertIsNone(result)
def test_symmetric_jws_token_plugin_with_illigal_key_exception(self): plugin = JWTTokenApi("wrong_sauce") secret = open("./tests/fixtures/symmetric.key").read() key = jwt.JWK() key.import_key(kty="oct",k=secret) jwt_token = jwt.JWT({"alg": "HS256"}, {'host': "remote_host", 'port': "remote_port"}) jwt_token.make_signed_token(key) result = plugin.lookup(jwt_token.serialize()) self.assertIsNone(result)
def test_jwt_late_time(self, mock_time): plugin = JWTTokenApi("./tests/fixtures/public.pem") key = jwt.JWK() private_key = open("./tests/fixtures/private.pem", "rb").read() key.import_from_pem(private_key) jwt_token = jwt.JWT({"alg": "RS256"}, {'host': "remote_host", 'port': "remote_port", 'nbf': 100, 'exp': 200 }) jwt_token.make_signed_token(key) mock_time.return_value = 250 result = plugin.lookup(jwt_token.serialize()) self.assertIsNone(result)
def authenticate_device(device_id, token, table_name): try: ddb_table = DDB_RESOURCE.Table(table_name) key_type = "oct" key_template = {"k": None, "kty": key_type} response = ddb_table.scan(FilterExpression=Attr('id').eq(device_id)) # Should only return one item, anything else is wrong if len(response['Items']) != 1: return (False, {"result": "db lookup returned bad result count"}) device_record = response['Items'][0] device_key = device_record['deviceKey'] # Refuse disabled device if device_record['deviceStatus'] == "disabled": return (False, {"result": "device disabled"}) key = key_template key['k'] = device_key # Use key to decrypt token claims try: key = jwt.JWK(**key) ET = jwt.JWT(key=key, jwt=token).token claims = json.loads(ET.payload.decode('utf-8')) except: return (False, { "result": "decrypt failed -- " + str(sys.exc_info()[0]) + " -- " + str(sys.exc_info()[1]) }) # Check there is a device-id claim in the token if 'device_id' not in claims: return (False, {"result": "no id claims"}) # Check claimed id matches one given in header if claims['device_id'] == device_id: return (True, {"result": "matching ids"}) else: return (False, {"result": "no matching ids"}) except: return (False, { "result": str(sys.exc_info()[0]) + " -- " + str(sys.exc_info()[1]) })
def test_asymmetric_jws_token_plugin(self): plugin = JWTTokenApi("./tests/fixtures/public.pem") key = jwt.JWK() private_key = open("./tests/fixtures/private.pem", "rb").read() key.import_from_pem(private_key) jwt_token = jwt.JWT({"alg": "RS256"}, {'host': "remote_host", 'port': "remote_port"}) jwt_token.make_signed_token(key) result = plugin.lookup(jwt_token.serialize()) self.assertIsNotNone(result) self.assertEqual(result[0], "remote_host") self.assertEqual(result[1], "remote_port")
def test_symmetric_jws_token_plugin_with_illigal_key_exception(self): secret = open("./tests/fixtures/symmetric.key").read() key = jwt.JWK() key.import_key(kty="oct",k=secret) jwt_token = jwt.JWT({"alg": "HS256"}, {'host': "remote_host", 'port': "remote_port"}) jwt_token.make_signed_token(key) self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format(jwt_token=jwt_token.serialize()) self.stubs.Set(websocketproxy.ProxyRequestHandler, 'send_auth_error', staticmethod(lambda *args, **kwargs: None)) self.handler.server.token_plugin = token_plugins.JWTTokenApi("wrong_sauce") self.assertRaises(self.handler.server.EClose, self.handler.validate_connection)
def __init__(self, param: bytes, cookie: bytes, header: bytes, keyfile: str, sessttl: int): self.log = Logger() self.key = jwt.JWK() self.param = param self.cookie = cookie self.header = header # Very naive session store. Extract and improve if necessary. self.sessttl = sessttl self.sessions = set() with open(keyfile, 'rb') as stream: self.key.import_from_pem(stream.read())
def test_asymmetric_jws_token_plugin(self): key = jwt.JWK() private_key = open("./tests/fixtures/private.pem", "rb").read() key.import_from_pem(private_key) jwt_token = jwt.JWT({"alg": "RS256"}, {'host': "remote_host", 'port': "remote_port"}) jwt_token.make_signed_token(key) self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format(jwt_token=jwt_token.serialize()) self.stubs.Set(websocketproxy.ProxyRequestHandler, 'send_auth_error', staticmethod(lambda *args, **kwargs: None)) self.handler.server.token_plugin = token_plugins.JWTTokenApi("./tests/fixtures/public.pem") self.handler.validate_connection() self.assertEqual(self.handler.server.target_host, "remote_host") self.assertEqual(self.handler.server.target_port, "remote_port")
def test_asymmetric_jws_token_plugin_with_illigal_key_exception(self): key = jwt.JWK() private_key = open("./tests/fixtures/private.pem", "rb").read() key.import_from_pem(private_key) jwt_token = jwt.JWT({"alg": "RS256"}, { 'host': "remote_host", 'port': "remote_port" }) jwt_token.make_signed_token(key) self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format( jwt_token=jwt_token.serialize()) self.handler.server.token_plugin = token_plugins.JWTTokenApi( "wrong.pub") with self.assertRaises(self.handler.server.EClose): self.handler.validate_connection()
def test_symmetric_jws_token_plugin(self): secret = open("./tests/fixtures/symmetric.key").read() key = jwt.JWK() key.import_key(kty="oct", k=secret) jwt_token = jwt.JWT({"alg": "HS256"}, { 'host': "remote_host", 'port': "remote_port" }) jwt_token.make_signed_token(key) self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format( jwt_token=jwt_token.serialize()) self.handler.server.token_plugin = token_plugins.JWTTokenApi( "./tests/fixtures/symmetric.key") self.handler.validate_connection() self.assertEqual(self.handler.server.target_host, "remote_host") self.assertEqual(self.handler.server.target_port, "remote_port")
def test_asymmetric_jws_token_plugin(self): key = jwt.JWK() private_key = open("./tests/fixtures/private.pem", "rb").read() key.import_from_pem(private_key) jwt_token = jwt.JWT({"alg": "RS256"}, { 'host': "remote_host", 'port': "remote_port" }) jwt_token.make_signed_token(key) self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format( jwt_token=jwt_token.serialize()) self.handler.server.token_plugin = token_plugins.JWTTokenApi( "./tests/fixtures/public.pem") self.handler.validate_connection() self.assertEqual(self.handler.server.target_host, "remote_host") self.assertEqual(self.handler.server.target_port, "remote_port")
def test_jwt_late_time(self, mock_time): key = jwt.JWK() private_key = open("./tests/fixtures/private.pem", "rb").read() key.import_from_pem(private_key) jwt_token = jwt.JWT({"alg": "RS256"}, { 'host': "remote_host", 'port': "remote_port", 'nbf': 100, 'exp': 200 }) jwt_token.make_signed_token(key) self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format( jwt_token=jwt_token.serialize()) mock_time.return_value = 250 self.handler.server.token_plugin = token_plugins.JWTTokenApi( "./tests/fixtures/public.pem") with self.assertRaises(self.handler.server.EClose): self.handler.validate_connection()