From ae9debe6f078f316931cd02df4171d64e2feb132 Mon Sep 17 00:00:00 2001 From: JulianMaurin Date: Thu, 21 Jul 2022 17:30:31 +0200 Subject: [PATCH 1/6] fix(api_jwt): update audience typing & type checking --- jwt/api_jwt.py | 8 ++++---- tests/test_api_jwt.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/jwt/api_jwt.py b/jwt/api_jwt.py index b08e9502..255fb6fb 100644 --- a/jwt/api_jwt.py +++ b/jwt/api_jwt.py @@ -76,7 +76,7 @@ def decode_complete( detached_payload: Optional[bytes] = None, # passthrough arguments to _validate_claims # consider putting in options - audience: Optional[str] = None, + audience: Optional[Union[str, Iterable]] = None, issuer: Optional[str] = None, leeway: Union[int, float, timedelta] = 0, # kwargs @@ -150,7 +150,7 @@ def decode( detached_payload: Optional[bytes] = None, # passthrough arguments to _validate_claims # consider putting in options - audience: Optional[str] = None, + audience: Optional[Union[str, Iterable]] = None, issuer: Optional[str] = None, leeway: Union[int, float, timedelta] = 0, # kwargs @@ -180,8 +180,8 @@ def _validate_claims(self, payload, options, audience=None, issuer=None, leeway= if isinstance(leeway, timedelta): leeway = leeway.total_seconds() - if not isinstance(audience, (bytes, str, type(None), Iterable)): - raise TypeError("audience must be a string, iterable, or None") + if audience and not isinstance(audience, (str, Iterable)): + raise TypeError("audience must be a string, iterable or None") self._validate_required_claims(payload, options) diff --git a/tests/test_api_jwt.py b/tests/test_api_jwt.py index d0443e89..17a84b70 100644 --- a/tests/test_api_jwt.py +++ b/tests/test_api_jwt.py @@ -119,7 +119,7 @@ def test_decode_with_invalid_audience_param_throws_exception(self, jwt): jwt.decode(example_jwt, secret, audience=1, algorithms=["HS256"]) exception = context.value - assert str(exception) == "audience must be a string, iterable, or None" + assert str(exception) == "audience must be a string, iterable or None" def test_decode_with_nonlist_aud_claim_throws_exception(self, jwt): secret = "secret" From 58f71276d57dfb38bb601d5e31537087a88b50a7 Mon Sep 17 00:00:00 2001 From: JulianMaurin Date: Thu, 21 Jul 2022 17:31:20 +0200 Subject: [PATCH 2/6] doc(api): update decode.audience typing --- docs/api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api.rst b/docs/api.rst index 2f81b1f7..919b6af9 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -62,7 +62,7 @@ API Reference if ``verify_exp``, ``verify_iat``, and ``verify_nbf`` respectively is set to ``True``). - :param Iterable audience: optional, the value for ``verify_aud`` check + :param Union[str, Iterable] audience: optional, the value for ``verify_aud`` check :param str issuer: optional, the value for ``verify_iss`` check :param float leeway: a time margin in seconds for the expiration check :rtype: dict From 9ac51d92907b1090997bc74ad3788dccce2f9cf8 Mon Sep 17 00:00:00 2001 From: JulianMaurin Date: Thu, 21 Jul 2022 17:54:43 +0200 Subject: [PATCH 3/6] feat(test_api_jwt): ensure audience as bytes raises error --- tests/test_api_jwt.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_api_jwt.py b/tests/test_api_jwt.py index 17a84b70..54783e5c 100644 --- a/tests/test_api_jwt.py +++ b/tests/test_api_jwt.py @@ -419,6 +419,12 @@ def test_raise_exception_invalid_audience(self, jwt): with pytest.raises(InvalidAudienceError): jwt.decode(token, "secret", audience="urn-me", algorithms=["HS256"]) + def test_raise_exception_audience_as_bytes(self, jwt): + payload = {"some": "payload", "aud": ["urn:me", "urn:someone-else"]} + token = jwt.encode(payload, "secret") + with pytest.raises(InvalidAudienceError): + jwt.decode(token, "secret", audience="urn:me".encode(), algorithms=["HS256"]) + def test_raise_exception_invalid_audience_in_array(self, jwt): payload = { "some": "payload", From 07428f2b3ddd453dcc4be0b873fafbb62fe735c6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 21 Jul 2022 15:57:36 +0000 Subject: [PATCH 4/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_api_jwt.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_api_jwt.py b/tests/test_api_jwt.py index 54783e5c..bebe7d28 100644 --- a/tests/test_api_jwt.py +++ b/tests/test_api_jwt.py @@ -423,7 +423,9 @@ def test_raise_exception_audience_as_bytes(self, jwt): payload = {"some": "payload", "aud": ["urn:me", "urn:someone-else"]} token = jwt.encode(payload, "secret") with pytest.raises(InvalidAudienceError): - jwt.decode(token, "secret", audience="urn:me".encode(), algorithms=["HS256"]) + jwt.decode( + token, "secret", audience="urn:me".encode(), algorithms=["HS256"] + ) def test_raise_exception_invalid_audience_in_array(self, jwt): payload = { From f86b50cea7cfc96a33a71c082e82608c61a99a4c Mon Sep 17 00:00:00 2001 From: Asif Saif Uddin Date: Fri, 22 Jul 2022 13:34:17 +0600 Subject: [PATCH 5/6] refacto(api_jwt): precise typing Co-authored-by: Julian Maurin Update jwt/api_jwt.py Co-authored-by: Julian Maurin fix(jwt/api_jwt.py): backport future annotations --- jwt/api_jwt.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/jwt/api_jwt.py b/jwt/api_jwt.py index 255fb6fb..fae88e39 100644 --- a/jwt/api_jwt.py +++ b/jwt/api_jwt.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json import warnings from calendar import timegm @@ -76,7 +78,7 @@ def decode_complete( detached_payload: Optional[bytes] = None, # passthrough arguments to _validate_claims # consider putting in options - audience: Optional[Union[str, Iterable]] = None, + audience: Optional[Union[str, Iterable[str]]] = None, issuer: Optional[str] = None, leeway: Union[int, float, timedelta] = 0, # kwargs @@ -150,7 +152,7 @@ def decode( detached_payload: Optional[bytes] = None, # passthrough arguments to _validate_claims # consider putting in options - audience: Optional[Union[str, Iterable]] = None, + audience: Optional[Union[str, Iterable[str]]] = None, issuer: Optional[str] = None, leeway: Union[int, float, timedelta] = 0, # kwargs From 3ac14074756465e2ef0d5513e2d67817c92ff5e4 Mon Sep 17 00:00:00 2001 From: JulianMaurin Date: Fri, 22 Jul 2022 13:14:35 +0200 Subject: [PATCH 6/6] fix: handle audience=0 --- jwt/api_jwt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jwt/api_jwt.py b/jwt/api_jwt.py index fae88e39..91a6d2e8 100644 --- a/jwt/api_jwt.py +++ b/jwt/api_jwt.py @@ -182,7 +182,7 @@ def _validate_claims(self, payload, options, audience=None, issuer=None, leeway= if isinstance(leeway, timedelta): leeway = leeway.total_seconds() - if audience and not isinstance(audience, (str, Iterable)): + if audience is not None and not isinstance(audience, (str, Iterable)): raise TypeError("audience must be a string, iterable or None") self._validate_required_claims(payload, options)