{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreig65e3qjh5l62tdnjffywrpxztpm4aazkrfummt7dtpbuxnpsxwfe",
    "uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mpmjaeujsl62"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreigrr6tpfb7qzuxhkbroicaxemhf6yvw2skf4mozaaedlkisdfm42q"
    },
    "mimeType": "image/webp",
    "size": 81230
  },
  "path": "/dev_nestio_229945f10652e4/i-built-a-browser-only-jwt-creator-signer-hs256384512-verify-expiry-check-77-tests-3b49",
  "publishedAt": "2026-07-01T21:36:38.000Z",
  "site": "https://dev.to",
  "tags": [
    "webdev",
    "security",
    "javascript",
    "tools",
    "https://devnestio.pages.dev/jwt-creator/",
    "devnestio.pages.dev"
  ],
  "textContent": "Debugging JWT authentication usually means copying tokens between tabs and tools. I built a free, browser-only **JWT Creator & Signer** — create, sign, and verify JWTs entirely in your browser using the Web Crypto API.\n\n##  Live Tool\n\nšŸ‘‰ https://devnestio.pages.dev/jwt-creator/\n\n##  What it does\n\n  * **Create JWTs** — edit header (alg, typ) and payload (any JSON)\n  * **Sign with HMAC** — HS256, HS384, or HS512\n  * **Quick claim buttons** — insert `sub`, `name`, `exp` (+1h), `iss` with one click\n  * **Generate random secrets** — 256-bit hex secret via `crypto.getRandomValues()`\n  * **Verify existing JWTs** — paste any token and verify signature + expiry\n  * **Color-coded output** — header in red, payload in green, signature in blue\n  * **100% client-side** — Web Crypto API, no server, your secrets stay local\n\n\n\n##  How signing works (Web Crypto API)\n\n\n    const key = await crypto.subtle.importKey(\n      \"raw\",\n      new TextEncoder().encode(secret),\n      { name: \"HMAC\", hash: \"SHA-256\" },\n      false, [\"sign\"]\n    );\n    const sig = await crypto.subtle.sign(\"HMAC\", key,\n      new TextEncoder().encode(header + \".\" + payload)\n    );\n\n\nThe output is base64url-encoded (replacing `+` → `-`, `/` → `_`, stripping `=` padding) to form the final JWT.\n\n##  Why browser-only matters for a JWT tool\n\nJWT secrets are sensitive. Any tool that sends your signing secret to a server is a liability. This tool never sends anything — the Web Crypto API runs entirely inside your browser tab.\n\n##  Testing\n\n**77 tests, all passing āœ…**\n\nTests cover:\n\n  * Base64url encoding edge cases\n  * JWT structure (3-part dot-separated)\n  * HMAC algorithm mapping (HS256 → SHA-256 etc.)\n  * Expiry check (expired vs. valid tokens)\n  * Error states: invalid JSON payload, malformed JWT\n  * UI: claim insertion, secret toggle, copy, clear\n  * Web Crypto API usage verification\n\n\n\nAll tools at devnestio.pages.dev — free browser-only developer utilities.\n\nFeedback welcome!",
  "title": "I built a browser-only JWT Creator & Signer — HS256/384/512, verify, expiry check, 77 tests"
}