Skip to content

fix(core): decode JWT payload as UTF-8#218

Merged
cameronapak merged 2 commits intomainfrom
fix/jwt-utf8-decode
Apr 28, 2026
Merged

fix(core): decode JWT payload as UTF-8#218
cameronapak merged 2 commits intomainfrom
fix/jwt-utf8-decode

Conversation

@bdhyv
Copy link
Copy Markdown
Contributor

@bdhyv bdhyv commented Apr 28, 2026

Summary

  • Decode JWT payload bytes as UTF-8 in YouVersionAPIUsers.decodeJWT() before JSON.parse to prevent mojibake for non-ASCII claims.
  • Keep existing behavior for invalid tokens by preserving the same error-handling path and empty-object fallback.
  • Add a regression test that validates accented + Cyrillic names decode correctly from base64url JWT payloads.

Test plan

  • YVP_API_HOST=api.youversion.com pnpm --filter @youversion/platform-core test -- src/__tests__/Users.test.ts

Made with Cursor

Greptile Summary

This PR fixes mojibake for non-ASCII JWT claims by converting the Latin-1 byte string returned by atob into a Uint8Array and re-decoding it as UTF-8 via TextDecoder before passing to JSON.parse. The change is minimal, correctly scoped, and the previous TextDecoder conditional-fallback concern from earlier review rounds has been resolved — the implementation now relies solely on the existing try/catch to handle any decode failure gracefully.

Confidence Score: 5/5

Safe to merge — no P0 or P1 findings; fix is correct, well-tested, and non-breaking.

The implementation correctly addresses the mojibake bug with a standard atobUint8ArrayTextDecoder pattern. All existing tests continue to pass (ASCII payloads are valid UTF-8), a dedicated regression test covers the non-ASCII case, and error paths remain unchanged. No P1 or P0 issues were identified.

No files require special attention.

Important Files Changed

Filename Overview
packages/core/src/Users.ts Adds UTF-8 decoding step after atob in decodeJWT using Uint8Array + TextDecoder; fix is correct and the try/catch handles any unavailability gracefully.
packages/core/src/tests/Users.test.ts Adds a regression test for non-ASCII claims (accented + Cyrillic); mock correctly simulates atob returning a Latin-1 byte string of the UTF-8 payload.
.changeset/khaki-dots-push.md Patch-level changeset entry for @youversion/platform-core; version bump type is appropriate for a bug fix.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[decodeJWT token] --> B{3 segments?}
    B -- No --> C[return empty object]
    B -- Yes --> D[base64url to standard base64 replace dashes and pad]
    D --> E{base64 truthy?}
    E -- No --> C
    E -- Yes --> F[atob base64 - Latin-1 byte string]
    F --> G[Uint8Array.from data via charCodeAt]
    G --> H[TextDecoder utf-8 .decode bytes]
    H --> I[JSON.parse decodedPayload]
    I --> J[return parsed object]
    I -- throws --> K[catch - return empty object]
Loading

Reviews (3): Last reviewed commit: "chore: add changeset for UTF-8 JWT decod..." | Re-trigger Greptile

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 28, 2026

🦋 Changeset detected

Latest commit: 5b50456

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@youversion/platform-core Patch
@youversion/platform-react-hooks Patch
@youversion/platform-react-ui Patch
vite-react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Comment thread packages/core/src/Users.ts Outdated
Comment thread packages/core/src/__tests__/Users.test.ts
Decode base64 JWT payload bytes as UTF-8 before JSON parsing to prevent mojibake for non-ASCII claims, and remove the Latin-1 fallback path so regressions cannot silently return garbled text.

Made-with: Cursor
@bdhyv bdhyv force-pushed the fix/jwt-utf8-decode branch from 99cad3b to acc863a Compare April 28, 2026 17:41
Mark a patch release for platform-core so the JWT decoding fix ships, and let the fixed package group advance hooks and ui to the same version.

Made-with: Cursor
Copy link
Copy Markdown
Collaborator

@cameronapak cameronapak left a comment

Choose a reason for hiding this comment

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

LGTM!

@cameronapak cameronapak merged commit 48a86d2 into main Apr 28, 2026
5 checks passed
@cameronapak cameronapak deleted the fix/jwt-utf8-decode branch April 28, 2026 18:39
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.

2 participants