JWT Debugger — Python source
Decode a JSON Web Token and inspect its header and payload as pretty JSON, with exp/iat claim awareness and an expiry badge. Runs entirely in your browser.
This is the Python implementation — the same logic the interactive tool runs, in a shareable, citable form.
"""JWT base64url decoding helper — Python port.
Language: Python
CosmoDev polyglot showcase port of the `jwt` tool.
Ported from src/lib/jwt.ts.
Display source — part of CosmoDev's polyglot tool pages
(dev.cosmolabs.org).
Decode-only: JWT signature verification stays server-side; the page never
holds the secret. The single helper below converts a base64url string (the
alphabet used by every JWT header/payload segment) into text.
"""
import base64
def b64url_decode(s: str) -> str:
"""Decode a base64url string into text.
JWT segments use RFC 4648's URL-safe base64 alphabet: ``-`` and ``_``
replace ``+`` and ``/``, and the trailing ``=`` padding is usually omitted.
Python's ``base64.urlsafe_b64decode`` understands the URL-safe characters
but, by default, *silently discards* anything outside the alphabet — so we
drive the standard decoder ourselves with validation on:
1. map the URL-safe characters back to ``+`` / ``/``,
2. restore the stripped ``=`` padding so the length is a multiple of 4, then
3. decode with ``validate=True`` so any non-alphabet character raises
``binascii.Error`` (matching the TS throw on malformed input).
The decoded bytes are interpreted as Latin-1 (``iso-8859-1``): each byte
maps directly to the Unicode code point of the same value, mirroring the
Web ``atob`` binary-string convention so the full 0x00-0xFF byte range
round-trips. A UTF-8 decode would reject the 0x80-0xFF test vectors.
Args:
s: a base64url segment (e.g. a JWT header or payload).
Returns:
The decoded string.
Raises:
binascii.Error: if *s* contains characters outside the base64url
alphabet.
"""
# 1. URL-safe alphabet -> standard base64 alphabet that b64decode validates.
standard = s.translate(str.maketrans("-_", "+/"))
# 2. Restore stripped '=' padding so the length is a multiple of 4.
padding = len(standard) % 4
if padding:
standard += "=" * (4 - padding)
# 3. Strict decode — validate=True rejects anything outside the alphabet.
data = base64.b64decode(standard, validate=True)
# 4. Bytes -> text, byte-faithful (Latin-1), mirroring JS atob.
return data.decode("latin-1")
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →