Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't get policies: audience error. #402

Open
rcapp opened this issue Jan 12, 2023 · 3 comments
Open

Can't get policies: audience error. #402

rcapp opened this issue Jan 12, 2023 · 3 comments

Comments

@rcapp
Copy link

rcapp commented Jan 12, 2023

Hello, everyone!

I'm trying to use the get_policies function, but I'm getting errors related with the Audience. I cannot find where in Keycloak I set them, so I'm not able to see if they are doubled (one of the errors says there are too many audiences). It maybe a problem with my configuration, but could be a bug too. Nevertheless, here is how I'm doing it:

import jwt  # PyJWT Lib
import requests

from jwt.algorithms import RSAAlgorithm

token = keycloak_openid.token("test", "1q2w3e4r")
keys_endpoint = requests.get("http://172.20.0.4:8080/realms/demo/protocol/openid-connect/certs")
key_jwt = next(
        (kj for kj in keys_endpoint.json()["keys"] if kj["kid"] == "[key-removed]"), None
    )
public_key = RSAAlgorithm.from_jwk(json.dumps(key_jwt))
decoded = jwt.decode(token["id_token"], public_key, audience="demo-api", algorithms="RS256")  # it outputs fine

public_key = "-----BEGIN PUBLIC KEY-----\n" + keycloak_openid.public_key() + "\n-----END PUBLIC KEY-----"
keycloak_openid.load_authorization_config("config.json")
policies = keycloak_openid.get_policies(token["access_token"], audience="demo-api", method_token_info="decode", key=public_key)  # it crashes

These are the errors:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[76], line 1
----> 1 policies = keycloak_openid.get_policies(token["access_token"], method_token_info='decode', audience="buyer-api", key=key_decoded)

File ~/sandbox/keycloak/demo/venv/lib/python3.8/site-packages/keycloak/keycloak_openid.py:558, in KeycloakOpenID.get_policies(self, token, method_token_info, **kwargs)
    553 if not self.authorization.policies:
    554     raise KeycloakAuthorizationConfigError(
    555         "Keycloak settings not found. Load Authorization Keycloak settings."
    556     )
--> 558 token_info = self._token_info(token, method_token_info, **kwargs)
    560 if method_token_info == "introspect" and not token_info["active"]:
    561     raise KeycloakInvalidTokenError("Token expired or invalid.")

File ~/sandbox/keycloak/demo/venv/lib/python3.8/site-packages/keycloak/keycloak_openid.py:216, in KeycloakOpenID._token_info(self, token, method_token_info, **kwargs)
    214     token_info = self.introspect(token)
    215 else:
--> 216     token_info = self.decode_token(token, **kwargs)
    218 return token_info

File ~/sandbox/keycloak/demo/venv/lib/python3.8/site-packages/keycloak/keycloak_openid.py:526, in KeycloakOpenID.decode_token(self, token, key, algorithms, **kwargs)
    503 def decode_token(self, token, key, algorithms=["RS256"], **kwargs):
    504     """Decode user token.
    505 
    506     A JSON Web Key (JWK) is a JavaScript Object Notation (JSON) data
   (...)
    524     :rtype: dict
    525     """
--> 526     return jwt.decode(token, key, algorithms=algorithms, audience=self.client_id, **kwargs)

TypeError: decode() got multiple values for keyword argument 'audience'

The two commands bellow they also crashes:

policies = keycloak_openid.get_policies( ..., audience="account", ...) # same error as above

and without the audience parameter it crashes with the error bellow:

---------------------------------------------------------------------------
JWTClaimsError                            Traceback (most recent call last)
Cell In[109], line 1
----> 1 policies = keycloak_openid.get_policies(token["access_token"],  method_token_info="decode", key=public_key)  # it crashes too

File ~/sandbox/keycloak/demo/venv/lib/python3.8/site-packages/keycloak/keycloak_openid.py:558, in KeycloakOpenID.get_policies(self, token, method_token_info, **kwargs)
    553 if not self.authorization.policies:
    554     raise KeycloakAuthorizationConfigError(
    555         "Keycloak settings not found. Load Authorization Keycloak settings."
    556     )
--> 558 token_info = self._token_info(token, method_token_info, **kwargs)
    560 if method_token_info == "introspect" and not token_info["active"]:
    561     raise KeycloakInvalidTokenError("Token expired or invalid.")

File ~/sandbox/keycloak/demo/venv/lib/python3.8/site-packages/keycloak/keycloak_openid.py:216, in KeycloakOpenID._token_info(self, token, method_token_info, **kwargs)
    214     token_info = self.introspect(token)
    215 else:
--> 216     token_info = self.decode_token(token, **kwargs)
    218 return token_info

File ~/sandbox/keycloak/demo/venv/lib/python3.8/site-packages/keycloak/keycloak_openid.py:526, in KeycloakOpenID.decode_token(self, token, key, algorithms, **kwargs)
    503 def decode_token(self, token, key, algorithms=["RS256"], **kwargs):
    504     """Decode user token.
    505 
    506     A JSON Web Key (JWK) is a JavaScript Object Notation (JSON) data
   (...)
    524     :rtype: dict
    525     """
--> 526     return jwt.decode(token, key, algorithms=algorithms, audience=self.client_id, **kwargs)

File ~/sandbox/keycloak/demo/venv/lib/python3.8/site-packages/jose/jwt.py:157, in decode(token, key, algorithms, options, audience, issuer, subject, access_token)
    154 if not isinstance(claims, Mapping):
    155     raise JWTError("Invalid payload string: must be a json object")
--> 157 _validate_claims(
    158     claims,
    159     audience=audience,
    160     issuer=issuer,
    161     subject=subject,
    162     algorithm=algorithm,
    163     access_token=access_token,
    164     options=defaults,
    165 )
    167 return claims

File ~/sandbox/keycloak/demo/venv/lib/python3.8/site-packages/jose/jwt.py:484, in _validate_claims(claims, audience, issuer, subject, algorithm, access_token, options)
    481     _validate_exp(claims, leeway=leeway)
    483 if options.get("verify_aud"):
--> 484     _validate_aud(claims, audience=audience)
    486 if options.get("verify_iss"):
    487     _validate_iss(claims, issuer=issuer)

File ~/sandbox/keycloak/demo/venv/lib/python3.8/site-packages/jose/jwt.py:350, in _validate_aud(claims, audience)
    348     raise JWTClaimsError("Invalid claim format in token")
    349 if audience not in audience_claims:
--> 350     raise JWTClaimsError("Invalid audience")

JWTClaimsError: Invalid audience

Any help is appreciated! Cheers!

@rcapp
Copy link
Author

rcapp commented Jan 12, 2023

Quick update: I changed how the library behaves when checking the audience, haven't done any real work to test and validate. So I won't call it a "solution". Also, I'm not sure how much this change bellow would impact the rest of the library:

    def decode_token(self, token, key, algorithms=["RS256"], **kwargs):
        """Decode user token. """

        return jwt.decode(token, key, algorithms=algorithms, **kwargs)        

Then, I provide the intended audience (account) for the access_token, since I cannot pass a ID Token to use the client audience.

keycloak/keycloak#14398 -- this is more or less my situation and one of the replies mention the client_id should be used on ID Token, not on access_token.

Cheers!

@kantorv
Copy link

kantorv commented Apr 26, 2023

found a workaround here
#89 (comment)

@NdSaid
Copy link

NdSaid commented Oct 16, 2023

The error you're encountering seems to be related to how you are decoding and validating a JWT token using the PyJWT library in Python. The error messages are indicating problems with the audience (aud) claim in the JWT. The issue appears to be in the validation of the audience, which doesn't match what you expected.

To resolve this issue, follow these steps:

1.Review Audience (aud) Claim:
The error messages suggest that there is a problem with the audience claim in the JWT. Verify that the audience you are providing to the jwt.decode method ("demo-api") matches the audience in the token. In your code, it seems you're expecting the audience to be "demo-api".

2.Check Token Payload:
Print the contents of the token["id_token"] to see what audience is included in the token. Make sure the audience in the token matches what you're using in the jwt.decode method.
Verify that the aud claim in the decoded token matches the expected audience ("demo-api").

3.Ensure Proper Token Signing Algorithm:
Ensure that the token you are trying to decode (token["id_token"]) is signed using the RS256 algorithm since you are specifying algorithms="RS256" when calling jwt.decode. If the token uses a different signing algorithm, you will need to adjust the algorithm parameter accordingly.

Check Token Issuer (iss) Claim:
Additionally, you should verify that the issuer (iss) claim of the token ("iss") matches your Keycloak server's URL. You can add this check using the issuer parameter when calling jwt.decode.

Verify Token in Keycloak:
Manually verify the token in your Keycloak admin console to confirm the audience claim and other token attributes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants