From 6927cf8cabeeec40df90a0dd2f393a8844d3f061 Mon Sep 17 00:00:00 2001 From: Gasper Zejn Date: Tue, 9 Apr 2019 21:36:46 +0200 Subject: [PATCH 1/2] 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. --- jose/jws.py | 1 + tests/test_jwt.py | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/jose/jws.py b/jose/jws.py index 3d11629c..98ec8ada 100644 --- a/jose/jws.py +++ b/jose/jws.py @@ -141,6 +141,7 @@ def _encode_header(algorithm, additional_headers=None): json_header = json.dumps( header, separators=(',', ':'), + sort_keys=True, ).encode('utf-8') return base64url_encode(json_header) diff --git a/tests/test_jwt.py b/tests/test_jwt.py index 01409545..9ceb2391 100644 --- a/tests/test_jwt.py +++ b/tests/test_jwt.py @@ -107,6 +107,33 @@ def test_non_default_headers(self, claims, key, headers): for k, v in headers.items(): assert all_headers[k] == v + def test_deterministic_headers(self): + from collections import OrderedDict + from jose.utils import base64url_decode + + claims = {"a": "b"} + key = "secret" + + headers1 = OrderedDict(( + ('kid', 'my-key-id'), + ('another_key', 'another_value'), + )) + encoded1 = jwt.encode(claims, key, algorithm='HS256', headers=headers1) + encoded_headers1 = encoded1.split('.', 1)[0] + + headers2 = OrderedDict(( + ('another_key', 'another_value'), + ('kid', 'my-key-id'), + )) + encoded2 = jwt.encode(claims, key, algorithm='HS256', headers=headers2) + encoded_headers2 = encoded2.split('.', 1)[0] + + assert encoded_headers1 == encoded_headers2 + + # manually decode header to compare it to known good + decoded_headers1 = base64url_decode(encoded_headers1.encode('utf-8')) + assert decoded_headers1 == b"""{"alg":"HS256","another_key":"another_value","kid":"my-key-id","typ":"JWT"}""" + def test_encode(self, claims, key): expected = ( From bdccde7d80d55965cba75e1d43e1d392920fc2be Mon Sep 17 00:00:00 2001 From: Gasper Zejn Date: Wed, 10 Apr 2019 09:41:25 +0200 Subject: [PATCH 2/2] Add an entry in changelog. --- CHANGELOG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4d7654df..c9df8d21 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,8 @@ Major `#121 `_ * Make pyca/cryptography backend the preferred backend if multiple backends are present. `#122 `_ +* Allow for headless JWT by sorting headers when serializing. + `#136 `_ Bugfixes """"""""