Skip to content

Fix: SDK not parsing headers with claims other than String - #127

Open
pmathew92 wants to merge 1 commit into
masterfrom
fix/header-parsing
Open

Fix: SDK not parsing headers with claims other than String#127
pmathew92 wants to merge 1 commit into
masterfrom
fix/header-parsing

Conversation

@pmathew92

Copy link
Copy Markdown
Contributor

Changes

This PR fixes the issue of DecodeException being thrown when the header of the token contains claims other than String types.

References

Fixes #88

@pmathew92
pmathew92 requested a review from a team as a code owner August 6, 2026 09:17
@@ -0,0 +1,109 @@
# Design: Spec-complete JWT header parsing (issue #88)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pmathew92 do we need to push this too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No... we don't want this

@pmathew92
pmathew92 force-pushed the fix/header-parsing branch from 53ed992 to cb167c5 Compare August 6, 2026 09:21
@pmathew92 pmathew92 changed the title Fix/header parsing Fix: Fix SDK not parsing headers with claims other than String Aug 6, 2026
@pmathew92 pmathew92 changed the title Fix: Fix SDK not parsing headers with claims other than String Fix: SDK not parsing headers with claims other than String Aug 6, 2026
tree.put(entry.getKey(), new ClaimImpl(value));
stringHeader.put(entry.getKey(), stringifyHeaderValue(value));
}
header = Collections.unmodifiableMap(stringHeader);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Behavior change: getHeader() previously returned Gson's mutable map; it's now unmodifiable. Any caller that mutates the returned map will now hit UnsupportedOperationException. Since getHeader() is public API, call this out in the changelog/@deprecated note, or keep it mutable to stay source-compatible.

if (value.isJsonPrimitive()) {
return value.getAsString();
}
return value.toString();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A JSON null header value (e.g. {"kid":null}) isn't a primitive, so this returns the literal string "null" instead of null. The old Map<String,String> deserialization stored an actual null. Add an isJsonNull() check

signature = parts[2];
}

private void parseHeader(String json) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The catch (DecodeException e) { throw e; } then catch (Exception e) re-wrap pattern works but is a bit convoluted. Simpler: validate isJsonObject() outside the try, since fromJson(..., JsonElement.class) only throws on malformed JSON.

private void parseHeader(String json) {
final JsonObject object;
try {
JsonElement element = getGson().fromJson(json, JsonElement.class);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getGson() registers the JWTDeserializer for JWTPayload, which is irrelevant for parsing the header into a raw JsonElement. A plain new Gson() (or reused static instance) is clearer and avoids the unnecessary type-adapter setup on every decode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DecodeException when header contains array?

3 participants