Skip to content

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

// JWT base64url decoding helper — C++ (C++20) port of the jwt tool.

#include <iostream>
#include <stdexcept>
#include <string>
#include <string_view>

namespace jwt {

// Decode a base64url segment (JWT header/payload) to a byte-faithful string.
// The C++ standard library has no base64 codec, so the decoder is carried
// here. Throws std::invalid_argument on input outside the base64url
// alphabet — the TS throw analogue. std::string is byte-oriented, so the
// result keeps each decoded byte as one character, mirroring JS atob.
std::string b64urlDecode(std::string_view str) {
    // 1. URL-safe alphabet -> standard base64 alphabet.
    std::string s(str);
    for (char &c : s) {
        if (c == '-') c = '+';
        else if (c == '_') c = '/';
    }

    // 2. Restore stripped '=' padding so the length is a multiple of 4.
    if (s.size() % 4 == 1) throw std::invalid_argument("invalid base64url length");
    s.append((4 - s.size() % 4) % 4, '=');

    // 3. Strict decode: 4-char blocks -> 3 bytes, validating every char.
    auto index = [](char c) -> int {
        if (c >= 'A' && c <= 'Z') return c - 'A';
        if (c >= 'a' && c <= 'z') return c - 'a' + 26;
        if (c >= '0' && c <= '9') return c - '0' + 52;
        if (c == '+') return 62;
        if (c == '/') return 63;
        return -1; // '=' is only legal as the final 1-2 chars
    };
    std::string out;
    out.reserve(s.size() / 4 * 3);
    for (size_t q = 0; q < s.size(); q += 4) {
        int v[4] = {0, 0, 0, 0};
        int pad = 0;
        for (int k = 0; k < 4; ++k) {
            char c = s[q + k];
            if (c == '=') { ++pad; continue; }
            if (pad != 0 || (v[k] = index(c)) < 0)
                throw std::invalid_argument("invalid base64url input");
        }
        if (pad > 2 || (pad != 0 && q + 4 != s.size()))
            throw std::invalid_argument("invalid base64url padding");
        unsigned triple = ((unsigned)v[0] << 18) | ((unsigned)v[1] << 12) |
                          ((unsigned)v[2] << 6) | (unsigned)v[3];
        out += static_cast<char>(triple >> 16);
        if (pad < 2) out += static_cast<char>(triple >> 8);
        if (pad < 1) out += static_cast<char>(triple);
    }

    // 4. Bytes are kept byte-faithful (std::string is a byte buffer).
    return out;
}

} // namespace jwt

int main() {
    // eyJhbGciOiJIUzI1NiJ9 decodes to {"alg":"HS256"}
    std::cout << jwt::b64urlDecode("eyJhbGciOiJIUzI1NiJ9") << '\n';
}

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 →