diff --git a/google/auth/jwt.py b/google/auth/jwt.py index 9d7b76e73..21de8fe95 100644 --- a/google/auth/jwt.py +++ b/google/auth/jwt.py @@ -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) @@ -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 diff --git a/system_tests/secrets.tar.enc b/system_tests/secrets.tar.enc index 93947b264..a36de1bfb 100644 Binary files a/system_tests/secrets.tar.enc and b/system_tests/secrets.tar.enc differ diff --git a/tests/test_jwt.py b/tests/test_jwt.py index bc01ebfc7..d45d5daa9 100644 --- a/tests/test_jwt.py +++ b/tests/test_jwt.py @@ -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