Update python-keycloak requirement from <4.0.0,>=3.9.1 to >=3.9.1,<5.0.0 #1097
GitHub Actions / Test Report ubuntu-latest:3.10
failed
Dec 2, 2024 in 0s
89 tests run, 82 passed, 6 skipped, 1 failed.
Annotations
Check failure on line 182 in tests/auth/test_api.py
github-actions / Test Report ubuntu-latest:3.10
test_api.test_impersonate_user
TypeError: JWT.__init__() got an unexpected keyword argument 'options'
Raw output
url = 'https://localhost:8443/hps'
keycloak_client = <keycloak.keycloak_admin.KeycloakAdmin object at 0x7fc56b028e80>
def test_impersonate_user(url, keycloak_client):
"""
Test token exchange for impersonation, see https://www.rfc-editor.org/rfc/rfc8693.html
Requires activating the token-exchange feature in keycloak
by passing --features=token-exchange to the start command.
"""
username = f"test_user_{uuid.uuid4()}"
new_user = User(
username=username,
password="test_auth_client",
email=f"{username}@test.com",
first_name="Test",
last_name="User",
)
new_user = create_user(keycloak_client, new_user)
realm_clients = keycloak_client.get_clients()
rep_impersonation_client = next(
(x for x in realm_clients if x["clientId"] == "rep-impersonation"), None
)
assert rep_impersonation_client is not None
client = Client(
url=url,
client_id=rep_impersonation_client["clientId"],
client_secret=rep_impersonation_client["secret"],
)
r = None
try:
r = authenticate(
url=url,
client_id=rep_impersonation_client["clientId"],
client_secret=rep_impersonation_client["secret"],
scope="opendid offline_access",
grant_type="urn:ietf:params:oauth:grant-type:token-exchange",
subject_token=client.access_token,
requested_token_type="urn:ietf:params:oauth:token-type:refresh_token",
requested_subject=new_user.id,
verify=False,
)
except HPSError as e:
if e.response.status_code == 501 and "Feature not enabled" in e.reason:
pytest.skip(f"This test requires to enable the feature 'token-exchange' in keycloak.")
assert r is not None
assert "refresh_token" in r
refresh_token_impersonated = r["refresh_token"]
client_impersonated = Client(
url,
username=new_user.username,
grant_type="refresh_token",
refresh_token=refresh_token_impersonated,
client_id=rep_impersonation_client["clientId"],
client_secret=rep_impersonation_client["secret"],
)
assert client_impersonated.access_token is not None
assert client_impersonated.refresh_token is not None
keycloak_openid = KeycloakOpenID(
server_url=client.auth_api_url,
client_id="account",
realm_name="rep",
client_secret_key="**********",
verify=False,
)
KEYCLOAK_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n"
KEYCLOAK_PUBLIC_KEY += keycloak_openid.public_key()
KEYCLOAK_PUBLIC_KEY += "\n-----END PUBLIC KEY-----"
options = {"verify_signature": True, "verify_aud": True, "verify_exp": True}
> token_info = keycloak_openid.decode_token(
client_impersonated.access_token,
key=KEYCLOAK_PUBLIC_KEY,
options=options,
)
tests/auth/test_api.py:182:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.tox/py310-coverage/lib/python3.10/site-packages/keycloak/keycloak_openid.py:645: in decode_token
return self._verify_token(token, key, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
token = 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJkT3VqVmljeGQ4MWZJdUFXVkVJdnFkTTNnYWNsNXQ1V3pjWkhsMnY4MVNvIn0.eyJleHAiOjE3MzMxNjAxNjcsImlhdCI6MTczMzE2MDA0NywianRpIjoiZTQ1NzRhYWEtZDU0OS00MDRlLWExYzctYWFkYjJlMDg0MTAxIiwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6ODQ0My9ocHMvYXV0aC9yZWFsbXMvcmVwIiwiYXVkIjpbInJlYWxtLW1hbmFnZW1lbnQiLCJhY2NvdW50Il0sInN1YiI6ImE0NTY3YjJlLTRhNzctNDQ1Ni05Y2I0LTVkNTU2N2ZhMmRiZCIsInR5cCI6IkJlYXJlciIsImF6cCI6InJlcC1pbXBlcnNvbmF0aW9uIiwic2Vzc2lvbl9zdGF0ZSI6IjIwZjNjZGQ0LTM1NGQtNGRhYi1iYmU3LTkyNGQwZDUxNDdiOSIsInJlc291cmNlX2FjY2VzcyI6eyJyZWFsbS1tYW5hZ2VtZW50Ijp7InJvbGVzIjpbInZpZXctdXNlcnMiLCJxdWVyeS1ncm91cHMiLCJxdWVyeS11c2VycyJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJwcm9maWxlIGVtYWlsIG9mZmxpbmVfYWNjZXNzIG1pY3JvcHJvZmlsZS1qd3QiLCJzaWQiOiIyMGYzY2RkNC0zNTRkLTRkYWItYmJlNy05MjRkMGQ1MTQ3YjkiLCJ1cG4iOiJ0ZXN0X3VzZXJfYTQ4YzBlYTItMTFlMi00NWUyLWJhMDctZTYyMmEyMGExNTllIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLXJlcC0xIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdLCJuYW1lIjoiVGVzdCBVc2VyIiwiZ3JvdXBzIjpbImRlZmF1bHQtcm9sZXMtcmVwLTEiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl0sInByZWZlcnJlZF91c2VybmFtZSI6InRlc3RfdXNlcl9hNDhjMGVhMi0xMWUyLTQ1ZTItYmEwNy1lNjIyYTIwYTE1OWUiLCJnaXZlbl9uYW1lIjoiVGVzdCIsImZhbWlseV9uYW1lIjoiVXNlciIsImVtYWlsIjoidGVzdF91c2VyX2E0OGMwZWEyLTExZTItNDVlMi1iYTA3LWU2MjJhMjBhMTU5ZUB0ZXN0LmNvbSIsInVzZXJuYW1lIjoidGVzdF91c2VyX2E0OGMwZWEyLTExZTItNDVlMi1iYTA3LWU2MjJhMjBhMTU5ZSJ9.B0a90AWuE8E6d_hENdrs0Vp4pAE1WLD8jLPTbbH5N6zzFljdW34DzZAgLbHOH5d4-5dtuWup7B-YekUayY5B2WIyiz5zQQSBBt5b7LKvNUb52jepTNtzccZgCCvMkDf0atewfZpB7S8GykGG9jqzqZXrEBnvSQvI0QDwxwMRJQAQ6YwYMb1cbfWi25JfZ5iQGmsE_MPxd_xoXJiMovLIdotT7EjTM2H-JYpwK4LuQ04CeI-BmBpSCJmQ_kB94BFMSD4JMl-oLuUPqxAPz2wFxJ76HDqrKHcwqThepPUQ_oTRuP4trL6lW1CPvqEXB0Hdvd7frYHNa3CTiXoMNc32nQ'
key = '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvIxy6qdtMCYlQwSni3jmbzt3QRsZqZAuR5X/p3AAhkSMvfLHxLzXsEV91McvtNzEhOK1qeQr08pWvuvcwOzc+FpHr5u/1jT6ACZe1/RSD/xpie0aA6VTEfcOwXvIQMnx7OWh1JSZ1Aw6tAjdbrYtEyigYbJBETqkzzxgxFROUAr/oMzBbxlqXoK2j0r+SRdBSzwWXva64VKi9NvGbN9XlpxpZhsYzk3J1KVcwquhX8Upf2cZTFvEVCF9B3pOAkZPoSuT1N6PsUoQ5roY6HvcpLPJj22TFOGogduZNgbPUFkn/gEreT/pDQaooV2A3tlJG0QeO1ZroraBUxUPCjfRNwIDAQAB\n-----END PUBLIC KEY-----'
kwargs = {'options': {'verify_aud': True, 'verify_exp': True, 'verify_signature': True}}
leeway = 60
@staticmethod
def _verify_token(token, key: Union[jwk.JWK, jwk.JWKSet, None], **kwargs):
"""Decode and optionally validate a token.
:param token: The token to verify
:type token: str
:param key: Which key should be used for validation.
If not provided, the validation is not performed and the token is implicitly valid.
:type key: Union[jwk.JWK, jwk.JWKSet, None]
:param kwargs: Additional keyword arguments for jwcrypto's JWT object
:type kwargs: dict
:returns: Decoded token
"""
# keep the function free of IO
# this way it can be used by `decode_token` and `a_decode_token`
if key is not None:
leeway = kwargs.pop("leeway", 60)
> full_jwt = jwt.JWT(jwt=token, **kwargs)
E TypeError: JWT.__init__() got an unexpected keyword argument 'options'
.tox/py310-coverage/lib/python3.10/site-packages/keycloak/keycloak_openid.py:602: TypeError
Loading