Exemple #1
0
 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'))
Exemple #2
0
 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"))
Exemple #3
0
 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'))
Exemple #4
0
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)
Exemple #5
0
 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'])
Exemple #6
0
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',
    }
Exemple #7
0
 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'])
Exemple #8
0
    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)
Exemple #9
0
 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'])
Exemple #10
0
 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], '{')
Exemple #11
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'])
Exemple #12
0
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,
    )
Exemple #13
0
 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")
Exemple #14
0
 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")
Exemple #15
0
 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
Exemple #16
0
 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'])
Exemple #17
0
 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")
Exemple #18
0
    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')
Exemple #19
0
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
Exemple #20
0
 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'])
Exemple #21
0
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'] == ''
Exemple #22
0
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
Exemple #23
0
 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'))
Exemple #24
0
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()))
Exemple #25
0
def get_public_key() -> Generator[_RSAPublicKey, None, None]:
    yield jwk.loads(get_jwk(settings.PUBLIC_KEY).dict())