def test_jwe_decrypt_legacy_v1_expiry(self): expiry_seconds = 10 claims = {jose.CLAIM_ISSUED_AT: int(time()) - 15} jwe = jose.encrypt(claims, rsa_pub_key) legacy_patch = mock.patch.object( jose, 'legacy_decrypt', wraps=jose.legacy_decrypt ) spec_patch = mock.patch.object( jose, 'spec_compliant_decrypt', wraps=jose.spec_compliant_decrypt ) with legacy_patch as legacy_mock, spec_patch as spec_mock: with self.assertRaises(jose.Expired) as expiry_error: jose.decrypt(jwe, rsa_priv_key, expiry_seconds=expiry_seconds) expiration_time = claims[jose.CLAIM_ISSUED_AT] + expiry_seconds self.assertEqual(legacy_mock.call_count, 1) self.assertEqual(spec_mock.call_count, 0) self.assertEqual( expiry_error.exception.message, 'Token expired at {}'.format( jose._format_timestamp(expiration_time) ) )
def test_jwe_decrypt_legacy_v1_not_yet_valid(self): # not valid for another hour. claim_not_before = int(time()) + 3600 claims = {jose.CLAIM_NOT_BEFORE: claim_not_before} jwe = jose.encrypt(claims, rsa_pub_key) legacy_patch = mock.patch.object( jose, 'legacy_decrypt', wraps=jose.legacy_decrypt ) spec_patch = mock.patch.object( jose, 'spec_compliant_decrypt', wraps=jose.spec_compliant_decrypt ) with legacy_patch as legacy_mock, spec_patch as spec_mock: with self.assertRaises(jose.NotYetValid) as not_valid_error: jose.decrypt(jwe, rsa_priv_key) self.assertEqual(legacy_mock.call_count, 1) self.assertEqual(spec_mock.call_count, 0) self.assertEqual( not_valid_error.exception.message, 'Token not valid until {}'.format( jose._format_timestamp(claim_not_before) ) )
def test_jwe_no_error_with_iat_claim(self): claims = {jose.CLAIM_ISSUED_AT: int(time()) - 15} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) jose.decrypt(jose.deserialize_compact(et), rsa_priv_key, expiry_seconds=20)
def test_jwe(self): bad_key = {'k': RSA.generate(2048).exportKey('PEM')} for (alg, jwk), enc in product(self.algs, self.encs): jwe = jose.encrypt(claims, rsa_pub_key, enc=enc, alg=alg) # make sure the body can't be loaded as json (should be encrypted) try: json.loads(jose.b64decode_url(jwe.ciphertext)) self.fail() except ValueError: pass token = jose.serialize_compact(jwe) jwt = jose.decrypt(jose.deserialize_compact(token), rsa_priv_key) self.assertNotIn(jose._TEMP_VER_KEY, claims) self.assertEqual(jwt.claims, claims) # invalid key try: jose.decrypt(jose.deserialize_compact(token), bad_key) self.fail() except jose.Error as e: self.assertEqual(e.message, 'Incorrect decryption.')
def to_string(self, remote_key=None, remote_ip=None): """ Sign and encrypt this response. :param remote_key: Encrypt response to this key :param remote_ip: If no remote_key, look up a key for this remote_ip :type remote_key: str or None :type remote_ip: str or None :rtype: str """ sign_key = self._config.keys.private_key self._logger.debug("Signing response using key {!r}".format(sign_key)) jws = jose.sign(self._data, sign_key.jwk, alg=self._config.jose_alg) signed_claims = {'v1': jose.serialize_compact(jws)} self._logger.debug("Signed response: {!r}".format(signed_claims)) encrypt_key = remote_key if not encrypt_key: # default to the first key found using the remote_ip in case no key was supplied ip_keys = self._config.keys.lookup_by_ip(remote_ip) if not ip_keys: self._logger.warning( "Found no key for IP {!r}, can't encrypt response:\n{!r}". format(remote_ip, self._data)) raise EduIDAPIError( "No API Key found - can't encrypt response") encrypt_key = ip_keys[0] self._logger.debug("Encrypting claims to key {!r}".format(encrypt_key)) jwe = jose.encrypt(signed_claims, encrypt_key.jwk) return jose.serialize_compact(jwe)
def test_jwe_direct_encryption(self): symmetric_key = "tisasymmetrickey" jwe = jose.encrypt(claims, "", alg = "dir",enc="A128CBC-HS256", dir_key = symmetric_key) # make sure the body can't be loaded as json (should be encrypted) try: json.loads(jose.b64decode_url(jwe.ciphertext)) self.fail() except ValueError: pass token = jose.serialize_compact(jwe) jwt = jose.decrypt(jose.deserialize_compact(token),"", dir_key = symmetric_key) self.assertNotIn(jose._TEMP_VER_KEY, claims) self.assertEqual(jwt.claims, claims) # invalid key badkey = "1234123412341234" try: jose.decrypt(jose.deserialize_compact(token), '', dir_key=badkey) self.fail() except jose.Error as e: self.assertEqual(e.message, 'Mismatched authentication tags')
def to_string(self, remote_key = None, remote_ip = None): """ Sign and encrypt this response. :param remote_key: Encrypt response to this key :param remote_ip: If no remote_key, look up a key for this remote_ip :type remote_key: str or None :type remote_ip: str or None :rtype: str """ sign_key = self._config.keys.private_key self._logger.debug("Signing response using key {!r}".format(sign_key)) jws = jose.sign(self._data, sign_key.jwk, alg = self._config.jose_alg) signed_claims = {'v1': jose.serialize_compact(jws)} self._logger.debug("Signed response: {!r}".format(signed_claims)) encrypt_key = remote_key if not encrypt_key: # default to the first key found using the remote_ip in case no key was supplied ip_keys = self._config.keys.lookup_by_ip(remote_ip) if not ip_keys: self._logger.warning("Found no key for IP {!r}, can't encrypt response:\n{!r}".format( remote_ip, self._data )) raise EduIDAPIError("No API Key found - can't encrypt response") encrypt_key = ip_keys[0] self._logger.debug("Encrypting claims to key {!r}".format(encrypt_key)) jwe = jose.encrypt(signed_claims, encrypt_key.jwk) return jose.serialize_compact(jwe)
def internal_auth_temporary(event, context): """AWS_LAMBDA:auth_temporary_jwt Generate a valid token for temporary access. :param tt: Registration token. :type tt: str. :returns: str -- Authentication token used for API calls. """ #generate token now_time = time.time() end_time = time.time() + 31104000 claims = { 'exp': end_time, 'nbf': now_time, 'iss': 'medpass-aws', 'aud': 'webclient', 'iat': now_time, 'type': 'TEMPORARY', 'id': event['user_id'] } jwe_token = jose.encrypt(claims, {'k': PUBLIC_KEY}, enc='A256CBC-HS512') auth_token = jose.serialize_compact(jwe_token) output = {'Authorization': auth_token} return output
def test_jwe_compression(self): local_claims = copy(claims) for v in xrange(1000): local_claims['dummy_' + str(v)] = '0' * 100 jwe = jose.serialize_compact(jose.encrypt(local_claims, rsa_pub_key)) _, _, _, uncompressed_ciphertext, _ = jwe.split('.') jwe = jose.serialize_compact( jose.encrypt(local_claims, rsa_pub_key, compression='DEF')) _, _, _, compressed_ciphertext, _ = jwe.split('.') self.assertTrue( len(compressed_ciphertext) < len(uncompressed_ciphertext)) jwt = jose.decrypt(jose.deserialize_compact(jwe), rsa_priv_key) self.assertEqual(jwt.claims, local_claims)
def test_jwe_compression(self): local_claims = copy(claims) for v in xrange(1000): local_claims['dummy_' + str(v)] = '0' * 100 jwe = jose.serialize_compact(jose.encrypt(local_claims, rsa_pub_key)) _, _, _, uncompressed_ciphertext, _ = jwe.split('.') jwe = jose.serialize_compact(jose.encrypt(local_claims, rsa_pub_key, compression='DEF')) _, _, _, compressed_ciphertext, _ = jwe.split('.') self.assertTrue(len(compressed_ciphertext) < len(uncompressed_ciphertext)) jwt = jose.decrypt(jose.deserialize_compact(jwe), rsa_priv_key) self.assertEqual(jwt.claims, local_claims)
def test_jwe_add_header(self): add_header = {'foo': 'bar'} for (alg, jwk), enc in product(self.algs, self.encs): et = jose.serialize_compact( jose.encrypt(claims, rsa_pub_key, add_header=add_header)) jwt = jose.decrypt(jose.deserialize_compact(et), rsa_priv_key) self.assertEqual(jwt.header['foo'], add_header['foo'])
def test_jwe_add_header(self): add_header = {'foo': 'bar'} for (alg, jwk), enc in product(self.algs, self.encs): et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key, add_header=add_header)) jwt = jose.decrypt(jose.deserialize_compact(et), rsa_priv_key) self.assertEqual(jwt.header['foo'], add_header['foo'])
def test_jwe_invalid_dates_error(self): claims = {'exp': time() - 5} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) try: jose.decrypt(jose.deserialize_compact(et), rsa_priv_key) self.fail() # expecting expired token except ValueError: pass claims = {'nbf': time() + 5} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) try: jose.decrypt(jose.deserialize_compact(et), rsa_priv_key) self.fail() # expecting not valid yet except ValueError: pass
def test_decrypt_invalid_compression_error(self): jwe = jose.encrypt(claims, rsa_pub_key, compression='DEF') header = jose.b64encode_url('{"alg": "RSA-OAEP", ' '"enc": "A128CBC-HS256", "zip": "BAD"}') try: jose.decrypt(jose.JWE(*((header,) + (jwe[1:]))), rsa_priv_key) self.fail() except ValueError as e: self.assertEqual(e.message, 'Unsupported compression algorithm: BAD')
def test_jwe_not_yet_valid_error_with_nbf_claim(self): claims = {jose.CLAIM_NOT_BEFORE: int(time()) + 5} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) try: jose.decrypt(jose.deserialize_compact(et), rsa_priv_key) self.fail() # expecting not valid yet except jose.NotYetValid as e: pass self.assertEquals( e.args[0], 'Token not valid until {}'.format( jose._format_timestamp(claims[jose.CLAIM_NOT_BEFORE])))
def test_jwe_expired_error_with_exp_claim(self): claims = {jose.CLAIM_EXPIRATION_TIME: int(time()) - 5} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) try: jose.decrypt(jose.deserialize_compact(et), rsa_priv_key) self.fail() # expecting expired token except jose.Expired as e: pass self.assertEquals( e.args[0], 'Token expired at {}'.format( jose._format_timestamp(claims[jose.CLAIM_EXPIRATION_TIME])))
def auth_master_login_jwt(event, context): """AWS_LAMBDA:auth_master_login_jwt Authenticate a valid code/password combination. :param code: User identification code. :type code: str. :param password: User password. :type password: str. :returns: str -- Authentication token used for API calls. """ try: #generate password hash for comparison, a slow hash with multiple iterations is used to difficult attacks binary_hash = hashlib.pbkdf2_hmac('sha256', event['body-json']['password'], DYN_CONF['MASTER_SALT'], 10000) hashed_password = binascii.hexlify(binary_hash) #compare results if hashed_password == DYN_CONF['MASTER_PASSWORD']: #generate token now_time = time.time() end_time = time.time() + 31104000 claims = { 'exp': end_time, 'nbf': now_time, 'iss': 'medpass-aws', 'aud': 'webclient', 'iat': now_time, 'type': 'MASTER', 'id': 'MASTER' } jwe_token = jose.encrypt(claims, {'k': PUBLIC_KEY}, enc='A256CBC-HS512') auth_token = jose.serialize_compact(jwe_token) output = { 'status': 'success', 'Authorization': auth_token, 'type': 'MASTER' } else: output = {'status': 'error', 'message': 'failed login'} except: LOGGER.error(traceback.print_exc()) output = {'status': 'error', 'message': 'failed login'} return output
def test_jwe_expired_error_with_exp_claim(self): claims = {jose.CLAIM_EXPIRATION_TIME: int(time()) - 5} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) try: jose.decrypt(jose.deserialize_compact(et), rsa_priv_key) self.fail() # expecting expired token except jose.Expired as e: pass self.assertEquals( e.args[0], 'Token expired at {}'.format( jose._format_timestamp(claims[jose.CLAIM_EXPIRATION_TIME]) ) )
def test_jwe_not_yet_valid_error_with_nbf_claim(self): claims = {jose.CLAIM_NOT_BEFORE: int(time()) + 5} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) try: jose.decrypt(jose.deserialize_compact(et), rsa_priv_key) self.fail() # expecting not valid yet except jose.NotYetValid as e: pass self.assertEquals( e.args[0], 'Token not valid until {}'.format( jose._format_timestamp(claims[jose.CLAIM_NOT_BEFORE]) ) )
def test_jwe_expired_error_with_iat_claim(self): expiry_seconds = 10 claims = {jose.CLAIM_ISSUED_AT: int(time()) - 15} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) try: jose.decrypt(jose.deserialize_compact(et), rsa_priv_key, expiry_seconds=expiry_seconds) self.fail() # expecting expired token except jose.Expired as e: pass expiration_time = claims[jose.CLAIM_ISSUED_AT] + expiry_seconds self.assertEquals( e.args[0], 'Token expired at {}'.format( jose._format_timestamp(expiration_time)))
def test_jwe_adata(self): adata = '42' for (alg, jwk), enc in product(self.algs, self.encs): et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key, adata=adata)) jwt = jose.legacy_decrypt(jose.deserialize_compact(et), rsa_priv_key, adata=adata) # make sure signatures don't match when adata isn't passed in try: hdr, dt = jose.legacy_decrypt(jose.deserialize_compact(et), rsa_priv_key) self.fail() except jose.Error as e: self.assertEqual(e.message, 'Mismatched authentication tags') self.assertEqual(jwt.claims, claims)
def test_jwe_adata(self): adata = '42' for (alg, jwk), enc in product(self.algs, self.encs): et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key, adata=adata)) jwt = jose.decrypt(jose.deserialize_compact(et), rsa_priv_key, adata=adata) # make sure signaures don't match when adata isn't passed in try: hdr, dt = jose.decrypt(jose.deserialize_compact(et), rsa_priv_key) self.fail() except jose.Error as e: self.assertEqual(e.message, 'Mismatched authentication tags') self.assertEqual(jwt.claims, claims)
def test_jwe_expired_error_with_iat_claim(self): expiry_seconds = 10 claims = {jose.CLAIM_ISSUED_AT: int(time()) - 15} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) try: jose.decrypt(jose.deserialize_compact(et), rsa_priv_key, expiry_seconds=expiry_seconds) self.fail() # expecting expired token except jose.Expired as e: pass expiration_time = claims[jose.CLAIM_ISSUED_AT] + expiry_seconds self.assertEquals( e.args[0], 'Token expired at {}'.format( jose._format_timestamp(expiration_time) ) )
def encrypt_fluffy(msgtype, key, groupkey="", keyid=""): #print "MsgType: ", msgtype #print "GroupKey: ", groupkey #print "KeyId: ", keyid print '*****************************' print 'Performing Encryption on a ' + msgtype print '*****************************' msg = gsk.Gsk(msgtype, groupkey, keyid) s = gsk.printGsk(msg) j_obj = json.loads(s) #add and map fluffy claims into jwt claims pyld = map_payload(j_obj) print "Pretty output: " print json.dumps(pyld, indent=4) print "--------------" j_obj['header']['msgtyp'] = msgtype header = { 'kid': str(j_obj['payload']['keydata']['kid']), 'typ': str(j_obj['header']['msgtyp']) + ' ' + str(j_obj['header']['pvno']), 'cty': j_obj['payload']['type'], } aad = { 'aut': j_obj['security']['authtime'], 'non': j_obj['security']['nonce'], 'snu': j_obj['security']['seqnum'] } header['aad'] = aad jwe = jose.encrypt(pyld, '', add_header = header, alg='dir', dir_key=str(key)) print(jose.serialize_compact(jwe)) f = open ("ENC_" + header['typ'] +".txt", "w") f.write(jose.serialize_compact(jwe)); f.close();
def send_request(self, url, name, apikey): """ Encrypt the claims and POST it to url. :param url: The URL to POST the data to :param name: The HTTP parameter name to put the data in :param apikey: API Key to encrypt data with before posting :return: :type url: str | unicode :type apikey: eduid_api.keystore.APIKey """ self._logger.debug("Encrypting signed request using {!r}".format(apikey)) if not apikey.keytype == 'jose': raise EduIDAPIError("Non-jose API key unusuable with send_request") self._api_key = apikey jwe = jose.encrypt(self.signed_claims, apikey.jwk) data = {name: jose.serialize_compact(jwe)} self._logger.debug("Sending signed and encrypted request to {!r}".format(url)) self._request_result = requests.post(url, data = data) self._logger.debug("Result of request: {!r}".format(self._request_result)) return self._request_result
def test_encrypt_invalid_compression_error(self): try: jose.encrypt(claims, rsa_pub_key, compression='BAD') self.fail() except jose.Error: pass
# key for demonstration purposes external_key = RSA.generate(2048) mtb_key = RSA.generate(2048) # JWE encode - encrypt info using the public key MtB info = {'company': 'ACME', 'author': 'pepe', 'experiment': 'ID'} print "\n\t START" print "\t |" print "\t< Secret information:" + str(info) + " >" print "\t |" print "\t< Encrypt information (information, MtB public key) >" print "\t |" try: pub_jwk = {'k': mtb_key.publickey().exportKey('PEM')} jwe = jose.encrypt(info, pub_jwk) # issue the compact serialized version to the clients. this is what will be # transported along with requests to target systems. secret = jose.serialize_compact(jwe) print "\t OK" print "\t |" except: print "\tError encrypting information! " e = sys.exc_info()[0] print "Error: %s" % e exit() # JWT sign - Sign token using the private key External claims = { 'from': 'mindthebyte', 'exp': int(time()) + 3600,
def test_jwe_ignores_expired_token_if_validate_claims_is_false(self): claims = {jose.CLAIM_EXPIRATION_TIME: int(time()) - 5} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) jose.decrypt(jose.deserialize_compact(et), rsa_priv_key, validate_claims=False)
#!/usr/bin/env python import jose from jose.serialize import serialize_compact import json # Compression test plaintext = "Kh" + ("a" * 512) + "n!" jwe_header = { "alg":"A128KW", "enc":"A128GCM", "zip": "DEF" } keys = [{ "kty":"oct", "k":"i-ueSNQgcr0q7auC8YUrYg" }] jwe1 = jose.encrypt(jwe_header, keys, plaintext, protect="*") dec1 = jose.decrypt(jwe1, keys) print "Compact JWE with compression:" #print json.dumps(jwe1, indent=4, sort_keys=True) print serialize_compact(jwe1) print print "Decrypted, decompressed JWE:" print dec1 print # Criticality test payload = "Some day you may pass validation. Today is not that day." jws_header1 = { "alg":"HS256", "crit": ["alg"] } jws_header2 = { "alg":"HS256", "true_rings": 1, "crit": ["true_rings"] } keys = [{ "kty":"oct", "k":"i-ueSNQgcr0q7auC8YUrYg" }]
def _sign_and_encrypt(self, claims, priv_jwk, server_jwk, alg='RS256'): jws = jose.sign(claims, priv_jwk, alg=alg) signed_claims = {'v1': jose.serialize_compact(jws)} jwe = jose.encrypt(signed_claims, server_jwk) return jwe
def test_jwe_no_error_with_exp_claim(self): claims = {jose.CLAIM_EXPIRATION_TIME: int(time()) + 5} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)
#!/usr/bin/env python import jose from jose.serialize import serialize_compact plaintext = "Attack at dawn!" jwe_header = {"alg": "A128KW", "enc": "A128GCM"} jws_header = {"alg": "HS256"} keys = [{"kty": "oct", "k": "i-ueSNQgcr0q7auC8YUrYg"}] # Encrypt into the JSON serialization jwe1 = jose.encrypt(jwe_header, keys, plaintext) dec1 = jose.decrypt(jwe1, keys) print jwe1 print dec1 print # Encrypt into the compact serialization jwe2 = serialize_compact( \ jose.encrypt(jwe_header, keys, plaintext, protect="*")) dec2 = jose.decrypt(jwe2, keys) print jwe2 print dec2 print # Sign into the JSON serialization jws1 = jose.sign(jws_header, keys, plaintext) ver1 = jose.verify(jws1, keys) print jws1 print ver1 print
def test_jwe_no_error_with_nbf_claim(self): claims = {jose.CLAIM_NOT_BEFORE: int(time()) - 5} et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key)) jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)
def login(event, context): """AWS_LAMBDA:auth_login_jwt Authenticate a valid email/password combination. :param email: User identification email. :type email: str. :param password: User password. :type password: str. :returns: str -- Authentication token used for API calls. """ try: #request user data (password, active_status, salt and id) from user services login_data = 'email' in event['body-json'] and { 'email': event['body-json']['email'] } or { 'cpf': event['body-json']['cpf'] } response = LAMBDA_CLIENT.invoke( FunctionName= 'arn:aws:lambda:us-west-2:566614558620:function:user_get_credentials:' + ENVIRONMENT, Qualifier=ENVIRONMENT, InvocationType='RequestResponse', Payload=json.dumps(login_data), LogType='None') payload = json.loads(response['Payload'].read()) if response['StatusCode'] == 200 and payload['status'] == 'success': #if the user provided a captcha verify it works approved_captcha = False if 'g-captcha-response' in event[ 'body-json'] and payload['failed_login_attempts'] >= 3: #validate recaptcha google_response = requests.post( 'https://www.google.com/recaptcha/api/siteverify', data={ 'secret': '6LdZNSgUAAAAAE8caj0ckJluAdJ3mGPHrE6kZW_n', 'response': event['body-json']['g-captcha-response'], 'remoteip': event['source-ip'] }).json() approved_captcha = google_response['success'] #verify that the user is not locked or did provide a captcha if payload['failed_login_attempts'] < 3 or approved_captcha: #generate password hash for comparison, a slow hash with multiple iterations is used to difficult attacks binary_hash = hashlib.pbkdf2_hmac( 'sha256', event['body-json']['password'], payload['salt'], 10000) hashed_password = binascii.hexlify(binary_hash) if 'token_annonymous' in event['body-json']: annonymous_login = event['body-json']['token_annonymous'] == payload['token_annonymous'] and\ True or False else: annonymous_login = False #compare results and verify if user is active if (hashed_password == payload['password'] and payload['active']) or annonymous_login: #clear old password reset tokens USER_TABLE.update_item( Key={'user_id': payload['user_id']}, UpdateExpression= 'SET password_token=:password_token, failed_login_attempts=:failed_login_attempts', ExpressionAttributeValues={ ':password_token': {}, ':failed_login_attempts': 0 }) #generate token now_time = time.time() end_time = time.time() + 31104000 claims = { 'exp': end_time, 'nbf': now_time, 'iss': 'medpass-aws', 'aud': 'webclient', 'iat': now_time, 'type': payload['type'], 'id': payload['user_id'] } jwe_token = jose.encrypt(claims, {'k': PUBLIC_KEY}, enc='A256CBC-HS512') auth_token = jose.serialize_compact(jwe_token) output = { 'status': 'success', 'Authorization': auth_token, 'type': payload['type'] } #profile dependent information if 'profile_url' in payload: output['profile_url'] = payload['profile_url'] #type dependent information if payload['type'] == 'USER': pendencies_response = REPORT_TABLE.get_item( Key={'user_id': payload['user_id']}, ProjectionExpression='pendencies') if 'Item' in pendencies_response: output['pendencies'] = False else: output['pendencies'] = True elif payload['type'] == 'PRE-MEDIC': #warn user if data is being revisited user_response = USER_TABLE.get_item( Key={'user_id': payload['user_id']}, ProjectionExpression='profile')['Item'] if 'profile' in user_response: output['sent'] = True else: output['sent'] = False output['pendencies'] = True elif payload['type'] == 'MEDIC': output['pendencies'] = False else: #include a failed login attempt to user USER_TABLE.update_item( Key={'user_id': payload['user_id']}, UpdateExpression='ADD failed_login_attempts :one', ExpressionAttributeValues={':one': 1}) LOGGER.info('Incorrect login attempt at email: "' + event['body-json']['email'] + '".') output = {'status': 'error', 'message': 'failed login'} else: LOGGER.info('Locked out user login attempt at email: "' + event['body-json']['email'] + '"') output = { 'status': 'captcha', 'message': 'locked out user need to validate captcha' } else: LOGGER.error("Failed to request user credential." + payload['message']) output = {'status': 'error', 'message': 'failed login'} except: LOGGER.error(traceback.print_exc()) output = {'status': 'error', 'message': 'failed login'} return output
def _sign_and_encrypt(self, claims, priv_jwk, server_jwk, alg = 'RS256'): jws = jose.sign(claims, priv_jwk, alg=alg) signed_claims = {'v1': jose.serialize_compact(jws)} jwe = jose.encrypt(signed_claims, server_jwk) return jwe