def load_key(header, payload): jwk_set = self.fetch_jwk_set() try: return jwk.loads(jwk_set, header.get('kid')) except ValueError: jwk_set = self.fetch_jwk_set(force=True) return jwk.loads(jwk_set, header.get('kid'))
def load_key(header, payload): jwk_set = self.fetch_jwk_set() try: return jwk.loads(jwk_set, header.get("kid")) except ValueError: # re-try with new jwk set jwk_set = self.fetch_jwk_set(force=True) return jwk.loads(jwk_set, header.get("kid"))
def _load_jwk(self, header, payload): if self.oidc_settings['jwks'] is not None: try: return jwk.loads(self.oidc_settings['jwks'], header.get('kid')) except ValueError: pass # no jwks cached or couldn't use them if not self.oidc_settings['jwks_url']: raise ValueError('No JWKS available') self.oidc_settings['jwks'] = jwk_set = requests.get( self.oidc_settings['jwks_url']).json() return jwk.loads(jwk_set, header.get('kid'))
def handle_azure_oauth(provider, oauth_token): from aleph.model import Role # Get incoming token, extract header for use with certificate verification id_token = oauth_token.get("id_token") headerbit = id_token.split(".")[0] headerbit = base64.b64decode(headerbit).decode("utf8") headerbit = json.loads(headerbit) # Load OAuth certificates from Microsoft. # TODO: this can be cached 24 hours. log.debug("Fetching Azure OAuth keys...") res = requests.get(AZURE_KEYS_URL, timeout=10) public_key = jwk.loads(res.json(), kid=headerbit["kid"]) # Decode incoming token and verify against the MS cert token_data = jwt.decode(id_token, public_key) # Validate token_data.validate() email = token_data["email"] name = token_data["name"] log.debug("Decoded token: %s (%s)", email, name) user_id = "azure:%s" % email return Role.load_or_create(user_id, Role.USER, name, email=email)
def test_rsa_public_key(self): # https://tools.ietf.org/html/rfc7520#section-3.3 obj = read_file_path('jwk_public.json') key = jwk.loads(obj) new_obj = jwk.dumps(key) self.assertBase64IntEqual(new_obj['n'], obj['n']) self.assertBase64IntEqual(new_obj['e'], obj['e'])
def test_app(context, app): client_id = 'baa448a8-205c-4faa-a048-a10e4b32a136' client_secret = 'joWgziYLap3eKDL6Gk2SnkJoyz0F8ukB' resp = app.post('/auth/token', auth=(client_id, client_secret), data={ 'grant_type': 'client_credentials', 'scope': 'profile', }) assert resp.status_code == 200, resp.text data = resp.json() assert data == { 'token_type': 'Bearer', 'expires_in': 864000, 'scope': 'profile', 'access_token': data['access_token'], } config = context.get('config') key = jwk.loads( json.loads((config.config_path / 'keys/public.json').read_text())) token = jwt.decode(data['access_token'], key) assert token == { 'iss': config.server_url, 'sub': client_id, 'aud': client_id, 'iat': int(token['iat']), 'exp': int(token['exp']), 'scope': 'profile', }
def test_loads_okp_public_key(self): obj = { "x": "AD9E0JYnpV-OxZbd8aN1t4z71Vtf6JcJC7TYHT0HDbg", "crv": "Ed25519", "kty": "OKP" } key = jwk.loads(obj) new_obj = jwk.dumps(key) self.assertEqual(obj['x'], new_obj['x'])
def test_jwks(self): """Test that the keys look ok.""" pub, pem = generate_jwks() self.assertIn("keys", pub, pub.keys()) self.assertIn("kid", pub["keys"][0]) self.assertIn("alg", pub["keys"][0]) self.assertEqual("RS256", pub["keys"][0]["alg"]) self.assertIsInstance(jwk.loads(pem), _RSAPrivateKey)
def test_ec_private_key(self): # https://tools.ietf.org/html/rfc7520#section-3.2 obj = read_file_path('ec_private.json') key = jwk.loads(obj) new_obj = jwk.dumps(key, 'EC') self.assertEqual(new_obj['crv'], obj['crv']) self.assertBase64IntEqual(new_obj['x'], obj['x']) self.assertBase64IntEqual(new_obj['y'], obj['y']) self.assertBase64IntEqual(new_obj['d'], obj['d'])
def test_ec_public_key(self): # https://tools.ietf.org/html/rfc7520#section-3.1 obj = read_file_path('ec_public.json') key = jwk.loads(obj) new_obj = jwk.dumps(key) self.assertEqual(new_obj['crv'], obj['crv']) self.assertBase64IntEqual(new_obj['x'], obj['x']) self.assertBase64IntEqual(new_obj['y'], obj['y']) self.assertEqual(key.as_json()[0], '{')
def test_loads_okp_private_key(self): obj = { 'x': '11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo', 'd': 'nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A', 'crv': 'Ed25519', 'kty': 'OKP' } key = jwk.loads(obj) new_obj = jwk.dumps(key) self.assertEqual(obj['d'], new_obj['d'])
def get_public_key(private_key): return jwk.dumps( jwk.loads(private_key).public_key().public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo, ).decode(), kty=JWT_KEY_ALGORITHM, use="sig", kid=JWT_KEY_ID, alg=JWT_ALGORITHM, )
def _get_ms_jwk(self, token): try: jwks = requests.get(self.key_url).json() token_header = token.split(".")[0].encode() unverified_header = extract_header(token_header, jwt_errors.DecodeError) for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: logger.info(f'Identified key {key["kid"]}') return jwk.loads(key) except jwt_errors.DecodeError: logger.exception('Error parsing signing keys') raise AuthenticationError("Unable to parse signing keys")
def _get_ms_jwk(self, token: str) -> JsonWebKey: try: self.logger.info(f'Getting signing keys from {self.key_url}') token_header = token.split(".")[0].encode() jwks = self._request_ms_jwks() unverified_header = extract_header(token_header, jwt_errors.DecodeError) # Authlib 1.0.0 changed behaviour of loads in 1.0.0 if version.parse(authlib_version) >= version.parse('1.0.0'): # This can now raise a ValueError: Invalid JSON Web Key Set if # the key is not found return jwk.loads(jwks, unverified_header['kid']) else: for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: self.logger.info(f'Identified key {key["kid"]}') return jwk.loads(key) except jwt_errors.DecodeError: self.logger.exception('Error parsing signing keys') except ValueError: self.logger.exception('Error finding key') raise AuthenticationError("Unable to parse signing keys")
def extractPublicKey(self, key_containing_object): """Extracts a key from the given parameter. A list or a dict object will be treated as a JWK or JWKS structure. A string will be treated like a X509 certificate""" try: if isinstance(key_containing_object, dict): pub_key = jwk.loads(key_containing_object) elif isinstance(key_containing_object, list): newest_key = self.findMostRecentJWK(key_containing_object) pub_key = jwk.loads(newest_key) elif isinstance(key_containing_object, str): key_containing_object = key_containing_object.encode() crt_obj = x509.load_pem_x509_certificate(key_containing_object, default_backend()) pub_key = crt_obj.public_key() pubkey_string = self.getPublicKeyString(pub_key) if pubkey_string is None: logger.writeError("Public Key could not be extracted from certificate") else: return pubkey_string except Exception as e: logger.writeError("Public Key(s) could not be extracted from JSON Web Keys. {}".format(e)) raise
def test_rsa_private_key(self): # https://tools.ietf.org/html/rfc7520#section-3.4 obj = RSA_PRIVATE_KEY key = jwk.loads(obj) new_obj = jwk.dumps(key, 'RSA') self.assertBase64IntEqual(new_obj['n'], obj['n']) self.assertBase64IntEqual(new_obj['e'], obj['e']) self.assertBase64IntEqual(new_obj['d'], obj['d']) self.assertBase64IntEqual(new_obj['p'], obj['p']) self.assertBase64IntEqual(new_obj['q'], obj['q']) self.assertBase64IntEqual(new_obj['dp'], obj['dp']) self.assertBase64IntEqual(new_obj['dq'], obj['dq']) self.assertBase64IntEqual(new_obj['qi'], obj['qi'])
def extractPublicKey(self, key_containing_object): """Extracts a key from the given parameter. A list or a dict object will be treated as a JWK or JWKS structure. A string will be treated like a X509 certificate""" try: if isinstance(key_containing_object, dict): rsa_key = self.findJWKByAlg([key_containing_object], self.TOKEN_ALG) pub_key = jwk.loads(key_containing_object) elif isinstance(key_containing_object, list): rsa_key = self.findJWKByAlg(key_containing_object, self.TOKEN_ALG) pub_key = jwk.loads(rsa_key) elif isinstance(key_containing_object, str): key_containing_object = key_containing_object.encode() crt_obj = x509.load_pem_x509_certificate(key_containing_object, default_backend()) pub_key = crt_obj.public_key() pubkey_string = self.getPublicKeyString(pub_key) if pubkey_string is None: self.logger.writeError("Public Key could not be extracted from certificate") else: return pubkey_string except Exception as e: self.logger.writeError( "{}. Public Key could not be extracted from JSON Web Keys. Key object: {}".format( e, key_containing_object)) abort(500, "Public Key could not be extracted from JSON Web Keys")
def test_mac_computation(self): # https://tools.ietf.org/html/rfc7520#section-3.5 obj = { "kty": "oct", "kid": "018c0ae5-4d9b-471b-bfd6-eef314bc7037", "use": "sig", "alg": "HS256", "k": "hJtXIZ2uSN5kbQfbtTNWbpdmhkV8FJG-Onbc6mxCcYg" } key = jwk.loads(obj) new_obj = jwk.dumps(key) self.assertEqual(obj['k'], new_obj['k']) self.assertNotIn('use', new_obj) new_obj = jwk.dumps(key, use='sig') self.assertEqual(new_obj['use'], 'sig')
def handle_cognito_oauth(provider, oauth_token): from aleph.model import Role # Pull keys from Cognito server keys = requests.get(settings.OAUTH_CERT_URL).json() key = lambda header, payload: jwk.loads(keys, kid=header.get("kid")) # Verify id and access token id_token = jwt.decode( oauth_token.get("id_token"), key, claims_options={ "exp": {"essential": True}, "aud": {"essential": True, "value": settings.OAUTH_KEY}, }, ) id_token.validate() access_token = jwt.decode( oauth_token.get("access_token"), key, claims_options={"exp": {"essential": True}}, ) access_token.validate() # Cognito access_token uses client_id instead of aud if access_token.get("client_id") != settings.OAUTH_KEY: return False # Assign group and user permissions groups = set(access_token.get("cognito:groups", [])) user_id = "cognito:{}".format(id_token.get("sub")) role = Role.load_or_create( user_id, Role.USER, id_token.get("given_name"), email=id_token.get("email"), is_admin=settings.OAUTH_ADMIN_GROUP in groups, ) role.clear_roles() for role_name in groups: if role_name == settings.OAUTH_ADMIN_GROUP: continue foreign_id = "cognitogroup:%s" % role_name group_role = Role.load_or_create(foreign_id, Role.GROUP, role_name) role.add_role(group_role) log.debug("User %r is member of %r", role, group_role) return role
def test_rsa_private_key2(self): obj = { "kty": "RSA", "kid": "*****@*****.**", "use": "sig", "n": RSA_PRIVATE_KEY['n'], 'd': RSA_PRIVATE_KEY['d'], "e": "AQAB" } key = jwk.loads(obj) new_obj = jwk.dumps(key, 'RSA') self.assertBase64IntEqual(new_obj['n'], obj['n']) self.assertBase64IntEqual(new_obj['e'], obj['e']) self.assertBase64IntEqual(new_obj['d'], obj['d']) self.assertBase64IntEqual(new_obj['p'], RSA_PRIVATE_KEY['p']) self.assertBase64IntEqual(new_obj['q'], RSA_PRIVATE_KEY['q']) self.assertBase64IntEqual(new_obj['dp'], RSA_PRIVATE_KEY['dp']) self.assertBase64IntEqual(new_obj['dq'], RSA_PRIVATE_KEY['dq']) self.assertBase64IntEqual(new_obj['qi'], RSA_PRIVATE_KEY['qi'])
def test_empty_scope(context, app): client_id = '3388ea36-4a4f-4821-900a-b574c8829d52' client_secret = 'b5DVbOaEY1BGnfbfv82oA0-4XEBgLQuJ' resp = app.post('/auth/token', auth=(client_id, client_secret), data={ 'grant_type': 'client_credentials', 'scope': '', }) assert resp.status_code == 200, resp.text data = resp.json() assert 'scope' not in data config = context.get('config') key = jwk.loads( json.loads((config.config_path / 'keys/public.json').read_text())) token = jwt.decode(data['access_token'], key) assert token['scope'] == ''
def load_key(context: Context, filename: str): config = context.get('config') with (config.config_path / 'keys' / filename).open() as f: key = json.load(f) key = jwk.loads(key) return key
def load_key(header, payload): # TODO: cache this? jwk_set = requests.get(current_app.config['OIDC_JWKS_URL']).json() return jwk.loads(jwk_set, header.get('kid'))
def test_genkeys(cli, tmpdir): result = cli.invoke(genkeys, ['-p', str(tmpdir)], catch_exceptions=False) assert result.output == (f'Private key saved to {tmpdir}/private.json.\n' f'Public key saved to {tmpdir}/public.json.\n') jwk.loads(json.loads(tmpdir.join('private.json').read())) jwk.loads(json.loads(tmpdir.join('public.json').read()))
def get_public_key() -> Generator[_RSAPublicKey, None, None]: yield jwk.loads(get_jwk(settings.PUBLIC_KEY).dict())