diff --git a/jose/jwt.py b/jose/jwt.py index f47e4dd..e8900a4 100644 --- a/jose/jwt.py +++ b/jose/jwt.py @@ -352,8 +352,8 @@ def _validate_aud(claims, audience=None): """ if "aud" not in claims: - # if audience: - # raise JWTError('Audience claim expected, but not in claims') + if audience is not None: + raise JWTClaimsError("Token is missing the 'aud' claim") return audience_claims = claims["aud"] diff --git a/tests/test_jwt.py b/tests/test_jwt.py index f9d54cd..9244c2d 100644 --- a/tests/test_jwt.py +++ b/tests/test_jwt.py @@ -353,11 +353,17 @@ def test_aud_case_sensitive(self, key): with pytest.raises(JWTError): jwt.decode(token, key, audience="AUDIENCE") - def test_aud_empty_claim(self, claims, key): - aud = "audience" + def test_aud_missing_claim_no_audience(self, claims, key): + # Token without 'aud' and no audience expected: should pass + token = jwt.encode(claims, key) + jwt.decode(token, key) + def test_aud_missing_claim_with_audience(self, claims, key): + # Token without 'aud' but caller requires an audience: should be rejected + aud = "audience" token = jwt.encode(claims, key) - jwt.decode(token, key, audience=aud) + with pytest.raises(JWTError): + jwt.decode(token, key, audience=aud) def test_aud_not_string_or_list(self, key): aud = 1 @@ -522,12 +528,15 @@ def test_require(self, claims, key, claim, value): if callable(value): value = value() options = {"require_" + claim: True, "verify_" + claim: False} + # Only pass audience when the claim under test is actually "aud"; + # passing audience for other claims would wrongly trigger the missing-aud check. + audience = str(value) if claim == "aud" else None token = jwt.encode(claims, key) with pytest.raises(JWTError): - jwt.decode(token, key, options=options, audience=str(value)) + jwt.decode(token, key, options=options, audience=audience) new_claims = dict(claims) new_claims[claim] = value token = jwt.encode(new_claims, key) - jwt.decode(token, key, options=options, audience=str(value)) + jwt.decode(token, key, options=options, audience=audience)