Skip to content

Commit

Permalink
fix: ensure JWT segments have the right types (#1162)
Browse files Browse the repository at this point in the history
* fix: ensure JWT header is a dict before accessing its methods
  • Loading branch information
ret2libc committed Nov 15, 2022
1 parent 370293e commit fc843cd
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
15 changes: 13 additions & 2 deletions google/auth/jwt.py
Expand Up @@ -133,11 +133,12 @@ def _unverified_decode(token):
token (Union[str, bytes]): The encoded JWT.
Returns:
Tuple[str, str, str, str]: header, payload, signed_section, and
Tuple[Mapping, Mapping, str, str]: header, payload, signed_section, and
signature.
Raises:
ValueError: if there are an incorrect amount of segments in the token.
ValueError: if there are an incorrect amount of segments in the token or
segments of the wrong type.
"""
token = _helpers.to_bytes(token)

Expand All @@ -152,6 +153,16 @@ def _unverified_decode(token):
header = _decode_jwt_segment(encoded_header)
payload = _decode_jwt_segment(encoded_payload)

if not isinstance(header, Mapping):
raise ValueError(
"Header segment should be a JSON object: {0}".format(encoded_header)
)

if not isinstance(payload, Mapping):
raise ValueError(
"Payload segment should be a JSON object: {0}".format(encoded_payload)
)

return header, payload, signed_section, signature


Expand Down
Binary file modified system_tests/secrets.tar.enc
Binary file not shown.
23 changes: 23 additions & 0 deletions tests/test_jwt.py
Expand Up @@ -126,6 +126,29 @@ def test_decode_valid(token_factory):
assert payload["metadata"]["meta"] == "data"


def test_decode_header_object(token_factory):
payload = token_factory()
# Create a malformed JWT token with a number as a header instead of a
# dictionary (3 == base64d(M7==))
payload = b"M7." + b".".join(payload.split(b".")[1:])

with pytest.raises(ValueError) as excinfo:
jwt.decode(payload, certs=PUBLIC_CERT_BYTES)
assert excinfo.match(r"Header segment should be a JSON object: " + str(b"M7"))


def test_decode_payload_object(signer):
# Create a malformed JWT token with a payload containing both "iat" and
# "exp" strings, although not as fields of a dictionary
payload = jwt.encode(signer, "iatexp")

with pytest.raises(ValueError) as excinfo:
jwt.decode(payload, certs=PUBLIC_CERT_BYTES)
assert excinfo.match(
r"Payload segment should be a JSON object: " + str(b"ImlhdGV4cCI")
)


def test_decode_valid_es256(token_factory):
payload = jwt.decode(
token_factory(use_es256_signer=True), certs=EC_PUBLIC_CERT_BYTES
Expand Down

0 comments on commit fc843cd

Please sign in to comment.