Skip to content

JWT Debugger — PHP 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 PHP implementation — the same logic the interactive tool runs, in a shareable, citable form.

<?php
/*
 * JWT base64url decoding helper — PHP port.
 *
 * Language: PHP
 * 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 converts a base64url string (the
 * alphabet used by every JWT header/payload segment) into text.
 */

declare(strict_types=1);

namespace CosmoDev\Jwt;

use InvalidArgumentException;

/**
 * Decode a base64url string into text.
 *
 * JWT segments use RFC 4648's URL-safe base64 alphabet: `-` and `_` replace
 * `+` and `/`, and the trailing `=` padding is normally omitted. PHP's native
 * `base64_decode` speaks only the standard alphabet, so we:
 *
 *   1. map the URL-safe characters back to `+` / `/`,
 *   2. restore the stripped `=` padding so the length is a multiple of 4, and
 *   3. decode in strict mode, which rejects characters outside the alphabet
 *      (the equivalent of the TS throw on malformed input).
 *
 * PHP strings are byte buffers, so `base64_decode` already yields a
 * byte-faithful value — each decoded byte becomes exactly one string byte,
 * mirroring the Web `atob` binary-string convention across the full
 * 0x00-0xFF range.
 *
 * @param string $str a base64url segment (e.g. a JWT header or payload)
 * @return string the decoded byte string
 * @throws InvalidArgumentException when $str is not valid base64url
 */
function b64urlDecode(string $str): string
{
    // 1. URL-safe alphabet -> standard base64 alphabet.
    $s = strtr($str, '-_', '+/');

    // 2. Restore any stripped '=' padding so the length is a multiple of 4.
    $pad = strlen($s) % 4;
    if ($pad !== 0) {
        $s .= str_repeat('=', 4 - $pad);
    }

    // 3. Strict decode — returns false on characters outside the alphabet,
    //    surfacing the same failure mode as the TS `atob` throw.
    $decoded = base64_decode($s, true);
    if ($decoded === false) {
        throw new InvalidArgumentException("invalid base64url input: {$str}");
    }

    return $decoded;
}

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 →