Skip to content

Commit 6927cf8

Browse files
committed
Sort headers when serializing to allow for headerless JWT.
Headers are usually small so this should not significantly impact performance. Testing both equality between two serialized values (fails on 3.6+ only) and equality with expected serialized JSON, which fails on pre 3.6 too.
1 parent 98fc909 commit 6927cf8

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

jose/jws.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ def _encode_header(algorithm, additional_headers=None):
141141
json_header = json.dumps(
142142
header,
143143
separators=(',', ':'),
144+
sort_keys=True,
144145
).encode('utf-8')
145146

146147
return base64url_encode(json_header)

tests/test_jwt.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,33 @@ def test_non_default_headers(self, claims, key, headers):
107107
for k, v in headers.items():
108108
assert all_headers[k] == v
109109

110+
def test_deterministic_headers(self):
111+
from collections import OrderedDict
112+
from jose.utils import base64url_decode
113+
114+
claims = {"a": "b"}
115+
key = "secret"
116+
117+
headers1 = OrderedDict((
118+
('kid', 'my-key-id'),
119+
('another_key', 'another_value'),
120+
))
121+
encoded1 = jwt.encode(claims, key, algorithm='HS256', headers=headers1)
122+
encoded_headers1 = encoded1.split('.', 1)[0]
123+
124+
headers2 = OrderedDict((
125+
('another_key', 'another_value'),
126+
('kid', 'my-key-id'),
127+
))
128+
encoded2 = jwt.encode(claims, key, algorithm='HS256', headers=headers2)
129+
encoded_headers2 = encoded2.split('.', 1)[0]
130+
131+
assert encoded_headers1 == encoded_headers2
132+
133+
# manually decode header to compare it to known good
134+
decoded_headers1 = base64url_decode(encoded_headers1.encode('utf-8'))
135+
assert decoded_headers1 == b"""{"alg":"HS256","another_key":"another_value","kid":"my-key-id","typ":"JWT"}"""
136+
110137
def test_encode(self, claims, key):
111138

112139
expected = (

0 commit comments

Comments
 (0)