Skip to content

Commit 7f7d524

Browse files
r-springermark-adams
authored andcommitted
Allow list of valid audiences to be passed in to PyJWT.decode() (jpadilla#306)
Resolves jpadilla#205,
1 parent c1253ec commit 7f7d524

File tree

8 files changed

+31
-11
lines changed

8 files changed

+31
-11
lines changed

AUTHORS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@ Patches and Suggestions
2323
- Wouter Bolsterlee <uws@xs4all.nl>
2424

2525
- Michael Davis <mike.philip.davis@gmail.com> <mike.davis@workiva.com>
26+
27+
- Vinod Gupta <codervinod@gmail.com>

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1010

1111
- Dropped support for python 2.6 and 3.3 [#297][297]
1212

13+
- Audience parameter now supports iterables [#205][205]
14+
1315
### Fixed
16+
1417
### Added
1518

1619
[v1.5.3][1.5.3]

jwt/api_jws.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import binascii
22
import json
33
import warnings
4-
54
from collections import Mapping
65

76
from .algorithms import (

jwt/api_jwt.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import json
22
import warnings
3-
43
from calendar import timegm
5-
from collections import Mapping
4+
from collections import Iterable, Mapping
65
from datetime import datetime, timedelta
76

87
from .api_jws import PyJWS
@@ -103,8 +102,8 @@ def _validate_claims(self, payload, options, audience=None, issuer=None,
103102
if isinstance(leeway, timedelta):
104103
leeway = leeway.total_seconds()
105104

106-
if not isinstance(audience, (string_types, type(None))):
107-
raise TypeError('audience must be a string or None')
105+
if not isinstance(audience, (string_types, type(None), Iterable)):
106+
raise TypeError('audience must be a string, iterable, or None')
108107

109108
self._validate_required_claims(payload, options)
110109

@@ -177,7 +176,11 @@ def _validate_aud(self, payload, audience):
177176
raise InvalidAudienceError('Invalid claim format in token')
178177
if any(not isinstance(c, string_types) for c in audience_claims):
179178
raise InvalidAudienceError('Invalid claim format in token')
180-
if audience not in audience_claims:
179+
180+
if isinstance(audience, string_types):
181+
audience = [audience]
182+
183+
if not any(aud in audience_claims for aud in audience):
181184
raise InvalidAudienceError('Invalid audience')
182185

183186
def _validate_iss(self, payload, issuer):

jwt/contrib/algorithms/pycrypto.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import Crypto.Hash.SHA256
22
import Crypto.Hash.SHA384
33
import Crypto.Hash.SHA512
4-
54
from Crypto.PublicKey import RSA
65
from Crypto.Signature import PKCS1_v1_5
76

tests/test_api_jws.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11

22
import json
3-
43
from decimal import Decimal
54

65
from jwt.algorithms import Algorithm

tests/test_api_jwt.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11

22
import json
33
import time
4-
54
from calendar import timegm
65
from datetime import datetime, timedelta
76
from decimal import Decimal
@@ -92,7 +91,7 @@ def test_decode_with_invalid_audience_param_throws_exception(self, jwt):
9291
jwt.decode(example_jwt, secret, audience=1)
9392

9493
exception = context.value
95-
assert str(exception) == 'audience must be a string or None'
94+
assert str(exception) == 'audience must be a string, iterable, or None'
9695

9796
def test_decode_with_nonlist_aud_claim_throws_exception(self, jwt):
9897
secret = 'secret'
@@ -281,6 +280,23 @@ def test_check_audience_when_valid(self, jwt):
281280
token = jwt.encode(payload, 'secret')
282281
jwt.decode(token, 'secret', audience='urn:me')
283282

283+
def test_check_audience_list_when_valid(self, jwt):
284+
payload = {
285+
'some': 'payload',
286+
'aud': 'urn:me'
287+
}
288+
token = jwt.encode(payload, 'secret')
289+
jwt.decode(token, 'secret', audience=['urn:you', 'urn:me'])
290+
291+
def test_raise_exception_invalid_audience_list(self, jwt):
292+
payload = {
293+
'some': 'payload',
294+
'aud': 'urn:me'
295+
}
296+
token = jwt.encode(payload, 'secret')
297+
with pytest.raises(InvalidAudienceError):
298+
jwt.decode(token, 'secret', audience=['urn:you', 'urn:him'])
299+
284300
def test_check_audience_in_array_when_valid(self, jwt):
285301
payload = {
286302
'some': 'payload',

tests/utils.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import os
22
import struct
3-
43
from calendar import timegm
54
from datetime import datetime
65

0 commit comments

Comments
 (0)