Skip to content

Commit c5ee34e

Browse files
committed
Merge pull request jpadilla#174 from gabrielg/master
Fail on encode and decode of bad JWS header values
2 parents 96c029a + 2a93fc5 commit c5ee34e

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

jwt/api_jws.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from collections import Mapping
66

77
from .algorithms import Algorithm, get_default_algorithms # NOQA
8-
from .compat import text_type
9-
from .exceptions import DecodeError, InvalidAlgorithmError
8+
from .compat import string_types, text_type
9+
from .exceptions import DecodeError, InvalidAlgorithmError, InvalidTokenError
1010
from .utils import base64url_decode, base64url_encode, merge_dict
1111

1212

@@ -79,6 +79,7 @@ def encode(self, payload, key, algorithm='HS256', headers=None,
7979
header = {'typ': self.header_typ, 'alg': algorithm}
8080

8181
if headers:
82+
self._validate_headers(headers)
8283
header.update(headers)
8384

8485
json_header = json.dumps(
@@ -125,7 +126,10 @@ def get_unverified_header(self, jwt):
125126
Note: The signature is not verified so the header parameters
126127
should not be fully trusted until signature verification is complete
127128
"""
128-
return self._load(jwt)[2]
129+
headers = self._load(jwt)[2]
130+
self._validate_headers(headers)
131+
132+
return headers
129133

130134
def _load(self, jwt):
131135
if isinstance(jwt, text_type):
@@ -180,6 +184,13 @@ def _verify_signature(self, payload, signing_input, header, signature,
180184
except KeyError:
181185
raise InvalidAlgorithmError('Algorithm not supported')
182186

187+
def _validate_headers(self, headers):
188+
if 'kid' in headers:
189+
self._validate_kid(headers['kid'])
190+
191+
def _validate_kid(self, kid):
192+
if not isinstance(kid, string_types):
193+
raise InvalidTokenError('Key ID header parameter must be a string')
183194

184195
_jws_global_obj = PyJWS()
185196
encode = _jws_global_obj.encode

tests/test_api_jws.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from jwt.algorithms import Algorithm
77
from jwt.api_jws import PyJWS
88
from jwt.exceptions import (
9-
DecodeError, InvalidAlgorithmError
9+
DecodeError, InvalidAlgorithmError, InvalidTokenError
1010
)
1111
from jwt.utils import base64url_decode
1212

@@ -367,12 +367,24 @@ def test_decode_with_algo_none_and_verify_false_should_pass(self, jws, payload):
367367

368368
def test_get_unverified_header_returns_header_values(self, jws, payload):
369369
jws_message = jws.encode(payload, key='secret', algorithm='HS256',
370-
headers={'kid': 123})
370+
headers={'kid': 'toomanysecrets'})
371371

372372
header = jws.get_unverified_header(jws_message)
373373

374374
assert 'kid' in header
375-
assert header['kid'] == 123
375+
assert header['kid'] == 'toomanysecrets'
376+
377+
def test_get_unverified_header_fails_on_bad_header_types(self, jws, payload):
378+
# Contains a bad kid value (int 123 instead of string)
379+
example_jws = (
380+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6MTIzfQ'
381+
'.eyJzdWIiOiIxMjM0NTY3ODkwIn0'
382+
'.vs2WY54jfpKP3JGC73Vq5YlMsqM5oTZ1ZydT77SiZSk')
383+
384+
with pytest.raises(InvalidTokenError) as exc:
385+
jws.get_unverified_header(example_jws)
386+
387+
assert 'Key ID header parameter must be a string' == str(exc.value)
376388

377389
@pytest.mark.skipif(not has_crypto, reason='Not supported without cryptography library')
378390
def test_encode_decode_with_rsa_sha256(self, jws, payload):
@@ -597,3 +609,14 @@ def test_encode_headers_parameter_adds_headers(self, jws, payload):
597609

598610
assert 'testheader' in header_obj
599611
assert header_obj['testheader'] == headers['testheader']
612+
613+
def test_encode_fails_on_invalid_kid_types(self, jws, payload):
614+
with pytest.raises(InvalidTokenError) as exc:
615+
jws.encode(payload, 'secret', headers={'kid': 123})
616+
617+
assert 'Key ID header parameter must be a string' == str(exc.value)
618+
619+
with pytest.raises(InvalidTokenError) as exc:
620+
jws.encode(payload, 'secret', headers={'kid': None})
621+
622+
assert 'Key ID header parameter must be a string' == str(exc.value)

0 commit comments

Comments
 (0)