Skip to content

Commit e8746b0

Browse files
committed
Merge pull request jpadilla#72 from wbolster/issue-72
Invalid validation of audience claim
2 parents 086cdf5 + 00b72e3 commit e8746b0

File tree

2 files changed

+25
-51
lines changed

2 files changed

+25
-51
lines changed

jwt/__init__.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,9 @@ def verify_signature(payload, signing_input, header, signature, key='',
398398
else:
399399
leeway = leeway.total_seconds()
400400

401+
if not isinstance(audience, (basestring, type(None))):
402+
raise TypeError('audience must be a string or None')
403+
401404
try:
402405
algorithm = header['alg'].upper()
403406
key = prepare_key_methods[algorithm](key)
@@ -425,14 +428,20 @@ def verify_signature(payload, signing_input, header, signature, key='',
425428
if payload['exp'] < (utc_timestamp - leeway):
426429
raise ExpiredSignatureError('Signature has expired')
427430

428-
if audience is not None:
429-
if isinstance(audience, list):
430-
audiences = audience
431-
else:
432-
audiences = [audience]
433-
434-
if payload.get('aud') not in audiences:
431+
if 'aud' in payload:
432+
audience_claims = payload['aud']
433+
if isinstance(audience_claims, basestring):
434+
audience_claims = [audience_claims]
435+
if not isinstance(audience_claims, list):
436+
raise InvalidAudienceError('Invalid claim format in token')
437+
if any(not isinstance(c, basestring) for c in audience_claims):
438+
raise InvalidAudienceError('Invalid claim format in token')
439+
if audience not in audience_claims:
435440
raise InvalidAudienceError('Invalid audience')
441+
elif audience is not None:
442+
# Application specified an audience, but it could not be
443+
# verified since the token does not contain a claim.
444+
raise InvalidAudienceError('No audience claim in token')
436445

437446
if issuer is not None:
438447
if payload.get('iss') != issuer:

tests/test_jwt.py

Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -701,93 +701,58 @@ def test_ecdsa_related_key_preparation_methods(self):
701701
self.assertFalse('ES512' in jwt.prepare_key_methods)
702702

703703
def test_check_audience(self):
704-
audience = 'urn:foo'
705-
706704
payload = {
707705
'some': 'payload',
708-
'aud': 'urn:foo'
706+
'aud': 'urn:me'
709707
}
710-
711708
token = jwt.encode(payload, 'secret')
712-
decoded = jwt.decode(token, 'secret', audience=audience)
713-
709+
decoded = jwt.decode(token, 'secret', audience='urn:me')
714710
self.assertEqual(decoded, payload)
715711

716712
def test_check_audience_in_array(self):
717-
audience = ['urn:foo', 'urn:other']
718-
719713
payload = {
720714
'some': 'payload',
721-
'aud': 'urn:foo'
715+
'aud': ['urn:me', 'urn:someone-else']
722716
}
723-
724717
token = jwt.encode(payload, 'secret')
725-
decoded = jwt.decode(token, 'secret', audience=audience)
726-
718+
decoded = jwt.decode(token, 'secret', audience='urn:me')
727719
self.assertEqual(decoded, payload)
728720

729721
def test_raise_exception_invalid_audience(self):
730-
audience = 'urn:wrong'
731-
732722
payload = {
733723
'some': 'payload',
734-
'aud': 'urn:foo'
724+
'aud': 'urn:someone-else'
735725
}
736-
737726
token = jwt.encode(payload, 'secret')
738-
739727
self.assertRaises(
740728
jwt.InvalidAudienceError,
741-
lambda: jwt.decode(token, 'secret', audience=audience))
729+
lambda: jwt.decode(token, 'secret', audience='urn-me'))
742730

743731
def test_raise_exception_invalid_audience_in_array(self):
744-
audience = ['urn:wrong', 'urn:morewrong']
745-
746732
payload = {
747733
'some': 'payload',
748-
'aud': 'urn:foo'
734+
'aud': ['urn:someone', 'urn:someone-else']
749735
}
750-
751736
token = jwt.encode(payload, 'secret')
752-
753737
self.assertRaises(
754738
jwt.InvalidAudienceError,
755-
lambda: jwt.decode(token, 'secret', audience=audience))
739+
lambda: jwt.decode(token, 'secret', audience='urn:me'))
756740

757741
def test_raise_exception_token_without_audience(self):
758-
audience = 'urn:wrong'
759-
760742
payload = {
761743
'some': 'payload',
762744
}
763-
764745
token = jwt.encode(payload, 'secret')
765-
766746
self.assertRaises(
767747
jwt.InvalidAudienceError,
768-
lambda: jwt.decode(token, 'secret', audience=audience))
769-
770-
def test_raise_exception_token_without_audience_in_array(self):
771-
audience = ['urn:wrong', 'urn:morewrong']
772-
773-
payload = {
774-
'some': 'payload',
775-
}
776-
777-
token = jwt.encode(payload, 'secret')
778-
779-
self.assertRaises(
780-
jwt.InvalidAudienceError,
781-
lambda: jwt.decode(token, 'secret', audience=audience))
748+
lambda: jwt.decode(token, 'secret', audience='urn:me'))
782749

783750
def test_check_issuer(self):
784751
issuer = 'urn:foo'
785-
786752
payload = {
787753
'some': 'payload',
788754
'iss': 'urn:foo'
789755
}
790-
791756
token = jwt.encode(payload, 'secret')
792757
decoded = jwt.decode(token, 'secret', issuer=issuer)
793758

0 commit comments

Comments
 (0)