class JWT: __instance = jwt.JWT() @classmethod def init(cls, config): with open(config.get('jwt.private'), 'rb') as f: JWT.signing_key = jwt.jwk_from_pem(f.read()) with open(config.get('jwt.public'), 'rb') as f: JWT.verifying_key = jwt.jwk_from_pem(f.read()) @classmethod def encode(cls, user: str): return JWT.__instance.encode( { 'user': user, 'iat': get_int_from_datetime(datetime.datetime.now()) }, JWT.signing_key, alg='RS256') @classmethod def decode(cls, token: str): try: return JWT.__instance.decode(token, JWT.verifying_key)['user'] except Exception as e: print(e) return None
def get_bearer_token(): if not GH_APP_PRIVATE_KEY.exists(): return None app_id = os.environ['GITHUB_APP_ID'] with open(GH_APP_PRIVATE_KEY, 'rb') as fh: private_key = jwt.jwk_from_pem(fh.read()) i = jwt.JWT() # Generate the JWT payload = { # issued at time, 60 seconds in the past to allow for clock drift 'iat': jwt.utils.get_int_from_datetime( datetime.now(timezone.utc) - timedelta(seconds=60)), # JWT expiration time (10 minute maximum) 'exp': jwt.utils.get_int_from_datetime( datetime.now(timezone.utc) + timedelta(minutes=10)), # GitHub App's identifier 'iss': app_id, } return i.encode(payload, private_key, alg="RS256")
def makeOauth2Request(self, pemPrivateKey: bytes) -> OAuth2Token: key = jwk.JWK.from_pem(pemPrivateKey) payload = { "exp": time.time() + 300, "iss": self.clientId, "aud": self.baseUrl, "sub": "5f3ed190c32e5f000186bb76" } raw_jwt_token = jwt.JWT(header={"alg": "RS256"}, claims=payload) raw_jwt_token.make_signed_token(key) signed_token = raw_jwt_token.serialize() payload_data = f'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion={signed_token}' oauth_url = self.apiUrl + '/oauth2/token' res = requests.post(url=oauth_url, data=payload_data, auth=(self.clientId, self.clientSecret)) if res.status_code in range(200, 211): return OAuth2Token(res.text) else: raise Exception( f"## Error with OAuth 2.0 Request ##\n\tStatus Code: {res.status_code}\n\tResponse: {res.text}" )
def encode_token(payload, secret=''): key = jwk.JWK(k=secret, kty='oct') token = jwt.JWT(header={'alg': 'HS256'}, claims=payload) token.make_signed_token(key) output = token.serialize() if isinstance(output, str): return output return output.decode()
def create_jwt(): """ Create a Github App Authentication JSON Web Token Parameters ---------- app_id: string Application ID assigned to the GitHub Application Returns ------- string JSON Web Token (JWT) to use while requesting an GitHub Access Token """ if app_config.APP_DEBUG: print("github.create_jwt: start") app_id, app_secret, installation_id = get_gh_app_data() if not app_id or not app_secret or not installation_id: if app_config.APP_DEBUG: print( "github.remove_org_member: app_id, app_secret or installation_id not returned" ) raise Exception( "github.create_jwt: get_gh_app_data did not return all required variables" ) time_since_epoch_in_seconds = int(time.time()) payload = { # issued at time 'iat': time_since_epoch_in_seconds, # JWT expiration time 'exp': time_since_epoch_in_seconds + (10 * 60), # GitHub App ID 'iss': app_id } gh_app_key = "-----BEGIN RSA PRIVATE KEY-----\r\n" gh_app_key += app_secret gh_app_key += "\r\n-----END RSA PRIVATE KEY-----" try: enc_gh_app_key = bytes(gh_app_key, 'UTF-8') signing_key = jwt.jwk_from_pem(enc_gh_app_key) except Exception as e: raise Exception("github.create_jwt: Github Private Key not loaded") instance = jwt.JWT() token = instance.encode(payload, signing_key, alg='RS256') if app_config.APP_DEBUG: print("github.remove_org_member: end") return token
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) 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 __init__(self, server_secret=None): self.table_descs = TABLES self.user_table = "users" self.groups_table = "groups" self.smtp_server_port = 1025 self.enforce_access_rights = server_secret is not None self.jwt = jwt.JWT() if server_secret is not None: self.server_secret = jwt.jwk.OctetJWK(bytes(server_secret, "utf-8")) else: self.server_secret = None print("set server secret", self.server_secret, self.enforce_access_rights)
def generate_objective_token(cls, objective_key: str, authorizer: Authorizer, duration: timedelta = None): if duration is None: duration = timedelta(days=1) jwk_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'jwk.json') with open(jwk_path, 'r') as f: jwk = jwt.jwk_from_dict(json.load(f)) encoder = jwt.JWT() now = datetime.now(timezone.utc) payload = { 'sub': authorizer.sub, "iat": get_int_from_datetime(now), "exp": get_int_from_datetime(now + duration), "objective": objective_key } return encoder.encode(payload, jwk)
def get_task_token_objective(cls, token: str, authorizer: Authorizer) -> str: jwk_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'jwk.json') with open(jwk_path, 'r') as f: jwk = jwt.jwk_from_dict(json.load(f)) decoded = jwt.JWT().decode(token, jwk) try: Schema({ "sub": str, "objective": str, "exp": int, "iat": int }).validate(decoded) except SchemaError: raise InvalidException("The given task token is not valid") if authorizer.sub != decoded['sub']: raise ForbiddenException( "The given task token does not belong to this user") return decoded['objective']
def generate_reward_token(cls, authorizer: Authorizer, static: RewardSet = None, area: Optional[str] = None, boxes: List[RewardSet] = None, duration: timedelta = None, reason: Enum = None) -> str: from core.services.beneficiaries import BeneficiariesService if duration is None: duration = timedelta(days=7) jwk_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'jwk.json') with open(jwk_path, 'r') as f: jwk = jwt.jwk_from_dict(json.load(f)) encoder = jwt.JWT() now = datetime.now(timezone.utc) token_index = int(BeneficiariesService.add_token_index(authorizer)) payload = { "sub": authorizer.sub, "iat": get_int_from_datetime(now), "exp": get_int_from_datetime(now + duration), "static": static.to_map_list() if static is not None else [], "boxes": [box.to_map_list() for box in boxes] if boxes is not None else [], "index": token_index, "area": area, "reason": None if reason is None else reason.value } return encoder.encode(payload, jwk)
def __init__(self, server_secret=None, data_dir="data"): self.collections_table = "collections" self.skeleton_table = "skeletons" self.motion_table = "motion_clips" self.preprocessed_table = "preprocessed_data" self.model_table = "models" self.graph_table = "graphs" self.user_table = "users" self.groups_table = "user_groups" self.character_dir = data_dir + os.sep + "characters" self.existing_collections = [] self.upload_buffer = dict() self.skeletons = dict() self._mp_buffer = dict() self._mp_skeleton_type = dict() self.jwt = jwt.JWT() if server_secret is not None: self.server_secret = jwt.jwk.OctetJWK(bytes( server_secret, "utf-8")) else: self.server_secret = None self.enforce_access_rights = server_secret is not None
def test_reward_token(ddb_stubber: Stubber): authorizer = Authorizer({"claims": {"sub": "abcABC123"}}) static_rewards = RewardSet(rewards=[ RewardProbability(category=RewardType.POINTS, rarity=RewardRarity.COMMON), ]) box_rewards = [ RewardSet(rewards=[ RewardProbability(category=RewardType.ZONE, rarity=RewardRarity.RARE), RewardProbability(category=RewardType.AVATAR, rarity=RewardRarity.RARE), ]) ] update_params = { 'TableName': 'beneficiaries', 'Key': { 'user': '******' }, 'ExpressionAttributeNames': { '#attr_generated_token_last': 'generated_token_last' }, 'ExpressionAttributeValues': { ':val_generated_token_last': 1 }, 'UpdateExpression': 'ADD #attr_generated_token_last :val_generated_token_last', 'ReturnValues': 'UPDATED_NEW' } update_response = {'Attributes': {'generated_token_last': {'N': str(10)}}} ddb_stubber.add_response('update_item', update_response, update_params) token = RewardsService.generate_reward_token( authorizer, static=static_rewards, boxes=box_rewards, reason=RewardReason.PROGRESS_LOG, area='corporality') ddb_stubber.assert_no_pending_responses() decoded = jwt.JWT().decode(token, do_verify=False) schema.Schema({ 'sub': 'abcABC123', 'reason': 'PROGRESS_LOG', 'index': 10, 'iat': 1577836800, 'exp': 1577836800 + 7 * 24 * 60 * 60, 'area': 'corporality', 'static': [{ 'type': 'POINTS', 'rarity': 'COMMON' }], 'boxes': [[{ 'type': 'ZONE', 'rarity': 'RARE' }, { 'type': 'AVATAR', 'rarity': 'RARE' }]] }).validate(decoded)
def decode_token(payload, secret=''): key = jwk.JWK(k=secret, kty='oct') jwt_token = jwt.JWT(key=key, jwt=payload) return json.loads(jwt_token.claims)
from hmac import compare_digest config = None try: config = configparser.ConfigParser() config.read("server.config") except Exception as e: sys.stderr.write("Unable to read config because: {}".format(str(e))) sys.stderr.write("\nTerminating Program...") sys.exit(1) jwt_expiration = int(config["jwt"]["expiration"]) jwt_lock = None jwt_key = None jwt_obj = jwt.JWT() try: private_file = config["secret"]["jwt_private"] public_file = config["secret"]["jwt_public"] with open(private_file, "rb") as private,\ open(public_file, "rb") as public: jwt_lock = private.read() jwt_key = public.read() jwt_lock = jwt.jwk_from_pem(jwt_lock) jwt_key = jwt.jwk_from_pem(jwt_key) except Exception as e: raise Exception("Unable to read config {} and {}, error {}"\
def encrypt_token(payload, public_key_pem): jwk_key = jwk.JWK.from_pem(public_key_pem.encode('UTF-8')) header = {'enc': 'A128CBC-HS256', 'alg': 'RSA-OAEP'} jwt_token = jwt.JWT(header, payload) jwt_token.make_encrypted_token(jwk_key) return jwt_token.serialize()
def test_get_active_task(ddb_stubber: Stubber): params = { 'TableName': 'beneficiaries', 'Key': { 'user': '******' }, 'ProjectionExpression': 'target' } response = { 'Item': { 'target': { 'M': { 'completed': { 'BOOL': False }, 'created': { 'N': str(int(time.time())) }, 'objective': { 'S': 'puberty::corporality::2.3' }, 'original-objective': { 'S': ObjectivesService.get('puberty', 'corporality', 2, 3) }, 'personal-objective': { 'S': 'A new task' }, 'tasks': { 'L': [{ 'M': { 'completed': { 'BOOL': False }, 'description': { 'S': 'Sub-task 1' }, } }, { 'M': { 'completed': { 'BOOL': False }, 'description': { 'S': 'Sub-task 2' } } }] } } } } } ddb_stubber.add_response('get_item', response, params) timestamp = str(int(time.time()) * 1000 - 24 * 60 * 60 * 1000 - 1) ddb_stubber.add_response( 'query', { 'Items': [{ 'user': { 'S': 'u-sub' }, 'tag': { 'S': 'STATS::PROGRESS::PUBERTY::CORPORALITY::2.3::' + str(timestamp) }, 'timestamp': { 'N': timestamp }, 'log': { 'S': 'A log!' }, }] }, { 'KeyConditionExpression': Key('user').eq('u-sub') & Key('tag').begins_with( 'STATS::PROGRESS::PUBERTY::CORPORALITY::2.3::'), 'Limit': 1, 'ScanIndexForward': False, 'TableName': 'logs' }) response = get_user_active_task( HTTPEvent({ "pathParameters": { "sub": 'u-sub', "stage": 'puberty', "area": 'sociability', "subline": "2.3" }, "requestContext": { "authorizer": { "claims": { "sub": 'u-sub' } } } })) ddb_stubber.assert_no_pending_responses() assert response.status == 200 Schema({ 'area': 'corporality', 'stage': 'puberty', 'line': 2, 'subline': 3, 'completed': False, 'created': 1577836800, 'objective': 'puberty::corporality::2.3', 'original-objective': 'Trato de superar las dificultades físicas propias de mi crecimiento.', 'personal-objective': 'A new task', 'tasks': [{ 'completed': False, 'description': 'Sub-task 1' }, { 'completed': False, 'description': 'Sub-task 2' }], 'eligible_for_progress_reward': True, 'score': 80, 'token': str }).validate(response.body) decoded = jwt.JWT().decode(response.body['token'], do_verify=False) assert Schema({ 'sub': 'u-sub', 'iat': 1577836800, 'exp': 1577836800 + 1 * 24 * 60 * 60, 'objective': 'puberty::corporality::2.3' }).validate(decoded)
def claim_reward(cls, authorizer: Authorizer, reward_token: str, release: int, box_index: int = None) -> \ List[Reward]: from core.services.beneficiaries import BeneficiariesService jwk_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'jwk.json') with open(jwk_path, 'r') as f: jwk = jwt.jwk_from_dict(json.load(f)) decoder = jwt.JWT() try: decoded = decoder.decode(reward_token, jwk) except JWTDecodeError as e: raise InvalidException(f'Invalid token: {e.args}') now = get_int_from_datetime(datetime.now()) if now > decoded["exp"]: raise ForbiddenException("The reward token has expired") if authorizer.sub != decoded["sub"]: raise ForbiddenException( "This token does not belong to the claimer") BeneficiariesService.set_reward_index(authorizer, decoded['index']) boxes = decoded["boxes"] probabilities: List[RewardProbability] = [ RewardProbability.from_map(reward) for reward in decoded["static"] ] if len(boxes) > 0: if box_index is None: raise InvalidException("A box must be chosen") if box_index >= len(boxes): raise InvalidException( f"Box index out of range, it must be between 0 (inclusive) and {len(boxes)} (exclusive)" ) probabilities += [ RewardProbability.from_map(reward) for reward in boxes[box_index] ] rewards = [ RewardsService.get_random(probability.type, release, probability.rarity) for probability in probabilities ] LogsService.batch_create(logs=[ Log(sub=authorizer.sub, tag=join_key(LogTag.REWARD.name, rewards[reward_i].type.name, rewards[reward_i].id), log='Won a reward', data=rewards[reward_i].to_api_map(), append_timestamp=rewards[reward_i].type != RewardType.AVATAR) for reward_i in range(len(rewards)) ]) area: Optional[str] = decoded.get('area') areas: List[str] = VALID_AREAS if area is None else [area] scores = {} for r in rewards: if r.type != RewardType.POINTS: continue total_score = r.description['amount'] for a in areas: scores[a] = scores.get(a, 0) + (total_score / len(areas)) for key in scores: scores[key] = math.ceil(scores[key]) BeneficiariesService.add_score(authorizer.sub, scores) return rewards
def decrypt_token(token, private_key_pem): jwk_key = jwk.JWK.from_pem(private_key_pem.encode('UTF-8')) jwt_token = jwt.JWT(key=jwk_key, jwt=token, algs=['A128CBC-HS256', 'RSA-OAEP']) return json.loads(jwt_token.claims)
def test_complete_task(ddb_stubber: Stubber): now = int(time.time()) get_params = { 'Key': { 'user': '******' }, 'ProjectionExpression': 'target', 'TableName': 'beneficiaries' } get_response = { 'Item': { 'user': { 'S': 'abcABC1234' }, 'group': { 'S': 'district::group' }, 'unit-user': { 'S': 'unit::abcABC12345' }, 'full-name': { 'S': 'Name' }, 'nickname': { 'S': 'Name' }, 'birthdate': { 'S': '01-01-2001' }, 'score': { 'M': {} }, 'n_tasks': { 'M': {} }, 'bought_items': { 'M': {} }, 'set_base_tasks': { 'BOOL': False }, 'target': { 'M': { 'original-objective': { 'S': 'Original' }, 'personal-objective': { 'S': 'Personal' }, 'objective': { 'S': 'puberty::corporality::2.1' }, 'score': { 'N': str(0) } } } } } beneficiary_update_params = { 'TableName': 'beneficiaries', 'Key': { 'user': '******' }, 'ReturnValues': 'UPDATED_OLD', 'UpdateExpression': 'SET #attr_target=:val_target ADD #attr_score.#attr_score_corporality :val_score_corporality, ' '#attr_n_tasks.#attr_n_tasks_corporality :val_n_tasks_corporality', 'ExpressionAttributeNames': { '#attr_score': 'score', '#attr_n_tasks': 'n_tasks', '#attr_n_tasks_corporality': 'corporality', '#attr_score_corporality': 'corporality', '#attr_target': 'target', }, 'ConditionExpression': Attr('target').ne(None), 'ExpressionAttributeValues': { ':val_target': None, ':val_n_tasks_corporality': 1, ':val_score_corporality': 80 } } beneficiary_update_response = { "Attributes": { 'n_tasks': { 'M': { 'corporality': { 'N': str(2) } # this is one less than its current value } }, "target": { 'M': { 'tasks': { 'L': [{ 'M': { 'completed': { 'BOOL': True }, 'description': { 'S': 'Sub-task 1' }, } }, { 'M': { 'completed': { 'BOOL': True }, 'description': { 'S': 'Sub-task 2' } } }] }, 'personal-objective': { 'S': 'A new task' }, 'created': { 'N': str(now) }, 'objective': { 'S': 'puberty::corporality::2.1' }, 'original-objective': { 'S': ObjectivesService.get('puberty', 'corporality', 2, 1) }, } } } } tasks_params = { 'TableName': 'tasks', 'ReturnValues': 'NONE', 'Item': { 'completed': True, 'created': ANY, 'objective': 'puberty::corporality::2.1', 'original-objective': ANY, 'personal-objective': 'A new task', 'tasks': [{ 'completed': True, 'description': 'Sub-task 1' }, { 'completed': True, 'description': 'Sub-task 2' }], 'user': '******', } } tasks_response = { 'Attributes': { 'created': { 'N': str(time.time()) }, 'objective': { 'S': 'puberty::corporality::2.1' }, 'original-objective': { 'S': 'Original' }, 'personal-objective': { 'S': 'A new task' }, 'tasks': { 'L': [{ 'M': { 'completed': { 'BOOL': True }, 'description': { 'S': 'Sub-task 1' } } }, { 'M': { 'completed': { 'BOOL': True }, 'description': { 'S': 'Sub-task 2' } } }] }, 'user': { 'S': 'user-sub' }, } } update_response = {'Attributes': {'generated_token_last': {'N': str(10)}}} update_params = { 'ExpressionAttributeNames': { '#attr_generated_token_last': 'generated_token_last' }, 'ExpressionAttributeValues': { ':val_generated_token_last': 1 }, 'Key': { 'user': '******' }, 'ReturnValues': 'UPDATED_NEW', 'TableName': 'beneficiaries', 'UpdateExpression': 'ADD #attr_generated_token_last :val_generated_token_last' } logs_params = { 'TableName': 'logs', 'ReturnValues': 'NONE', 'Item': { 'tag': 'STATS::COMPLETED::PUBERTY::CORPORALITY::2.1', 'log': 'Completed an objective!', 'data': {}, 'timestamp': 1577836800000, 'user': '******' } } logs_response = {} ddb_stubber.add_response('get_item', get_response, get_params) ddb_stubber.add_response('update_item', beneficiary_update_response, beneficiary_update_params) ddb_stubber.add_response('put_item', tasks_response, tasks_params) ddb_stubber.add_response('update_item', update_response, update_params) ddb_stubber.add_response('put_item', logs_response, logs_params) response = complete_active_task( HTTPEvent({ "pathParameters": { "sub": 'user-sub' }, "requestContext": { "authorizer": { "claims": { "sub": 'user-sub' } } } })) assert response.status == 200 Schema({ 'message': 'Completed task', 'task': { 'tasks': [ { 'completed': True, 'description': 'Sub-task 1' }, { 'completed': True, 'description': 'Sub-task 2' }, ], 'personal-objective': 'A new task', 'created': Decimal(now), 'objective': 'puberty::corporality::2.1', 'original-objective': 'Comprendo que los cambios que se estan ' 'produciendo en mi cuerpo influyen en mi manera de ser.', 'completed': True, }, 'reward': str }).validate(response.body) reward_token = response.body['reward'] decoded = jwt.JWT().decode(reward_token, do_verify=False) Schema({ 'index': 10, 'sub': 'user-sub', 'iat': 1577836800, 'exp': 1577836800 + 7 * 24 * 60 * 60, 'area': 'corporality', 'reason': 'COMPLETE_OBJECTIVE', 'static': [ { 'type': 'NEEDS', 'rarity': 'RARE' }, { 'type': 'ZONE', 'rarity': 'RARE' }, { 'type': 'POINTS', 'rarity': 'RARE' }, ], 'boxes': [[{ 'type': 'AVATAR', 'rarity': 'RARE' }, { 'type': 'DECORATION', 'rarity': 'COMMON' }], [{ 'type': 'DECORATION', 'rarity': 'RARE' }, { 'type': 'AVATAR', 'rarity': 'COMMON' }], [{ 'type': 'AVATAR', 'rarity': 'RARE' }, { 'type': 'DECORATION', 'rarity': 'RARE' }]] }).validate(decoded) ddb_stubber.assert_no_pending_responses()
import jwt import aiohttp from datetime import datetime, timedelta, timezone from jwt.utils import get_int_from_datetime from auth import GITHUB_PEM_FILE, GITHUB_APP_ID instance = jwt.JWT() def new_jwt(): """Generate a new JSON Web Token signed by RSA private key.""" with open(GITHUB_PEM_FILE, 'rb') as fp: signing_key = jwt.jwk_from_pem(fp.read()) payload = { 'iat': get_int_from_datetime(datetime.now()), 'exp': get_int_from_datetime( datetime.now(timezone.utc) + timedelta(minutes=10)), 'iss': GITHUB_APP_ID } compact_jws = instance.encode(payload, signing_key, alg='RS256') return compact_jws async def new_token(_jwt): authorization = f"Bearer {_jwt}" headers = {