diff --git a/jose/jwt.py b/jose/jwt.py index 2da511fd..3ba32507 100644 --- a/jose/jwt.py +++ b/jose/jwt.py @@ -408,24 +408,28 @@ def _validate_jti(claims): def _validate_at_hash(claims, access_token, algorithm): """ - Validates that the 'at_hash' parameter included in the claims matches - with the access_token returned alongside the id token as part of - the authorization_code flow. + Validates that the 'at_hash' is valid. + + Its value is the base64url encoding of the left-most half of the hash + of the octets of the ASCII representation of the access_token value, + where the hash algorithm used is the hash algorithm used in the alg + Header Parameter of the ID Token's JOSE Header. For instance, if the + alg is RS256, hash the access_token value with SHA-256, then take the + left-most 128 bits and base64url encode them. The at_hash value is a + case sensitive string. Use of this claim is OPTIONAL. Args: - claims (dict): The claims dictionary to validate. - access_token (str): The access token returned by the OpenID Provider. - algorithm (str): The algorithm used to sign the JWT, as specified by - the token headers. + claims (dict): The claims dictionary to validate. + access_token (str): The access token returned by the OpenID Provider. + algorithm (str): The algorithm used to sign the JWT, as specified by + the token headers. """ - if 'at_hash' not in claims and not access_token: + if 'at_hash' not in claims: return - elif 'at_hash' in claims and not access_token: + + if not access_token: msg = 'No access_token provided to compare against at_hash claim.' raise JWTClaimsError(msg) - elif access_token and 'at_hash' not in claims: - msg = 'at_hash claim missing from token.' - raise JWTClaimsError(msg) try: expected_hash = calculate_at_hash(access_token, @@ -433,7 +437,7 @@ def _validate_at_hash(claims, access_token, algorithm): except (TypeError, ValueError): msg = 'Unable to calculate at_hash to verify against token claims.' raise JWTClaimsError(msg) - + if claims['at_hash'] != expected_hash: raise JWTClaimsError('at_hash claim does not match access_token.') diff --git a/tests/test_jwt.py b/tests/test_jwt.py index 485fff52..beb6789f 100644 --- a/tests/test_jwt.py +++ b/tests/test_jwt.py @@ -468,8 +468,8 @@ def test_at_hash_missing_access_token(self, claims, key): def test_at_hash_missing_claim(self, claims, key): token = jwt.encode(claims, key) - with pytest.raises(JWTError): - jwt.decode(token, key, access_token='') + payload = jwt.decode(token, key, access_token='') + assert 'at_hash' not in payload def test_at_hash_unable_to_calculate(self, claims, key): token = jwt.encode(claims, key, access_token='')