Skip to content

JWT Generator

Sign a new JWT (HS256) from a header, payload, and secret.

A JWT generator constructs a signed token from three inputs: a header (the algorithm and type), a payload (the claims you want to assert), and a key (a shared secret for HMAC algorithms or a private key for RSA/ECDSA). The output is the standard header.payload.signature triple, base64url-encoded. This tool runs entirely in your browser — no token, payload, or secret leaves your machine. It signs with HS256 only: you supply the payload and a shared secret, and the header is fixed at {"alg":"HS256","typ":"JWT"}. The RSA and ECDSA material below explains the other algorithms; to sign with those, use a library such as jose.

The three inputs

Header. A small JSON object that names the signing algorithm and token type:

{ "alg": "HS256", "typ": "JWT" }

alg is the signing algorithm. Common choices:

  • HS256 / HS384 / HS512 — HMAC with SHA-2; the key is a shared secret.
  • RS256 / RS384 / RS512 — RSA signature with SHA-2; you sign with a private key, verifiers check with the matching public key.
  • ES256 / ES384 / ES512 — ECDSA with SHA-2; same public/private key model as RSA but with smaller keys and signatures.

typ is conventionally "JWT" and is mostly informational.

Payload. A JSON object of claims. Standard claims have specific meanings under RFC 7519:

  • sub — subject, typically a user ID
  • iat — issued-at, Unix timestamp in seconds
  • exp — expiration, Unix timestamp in seconds
  • nbf — not-before, Unix timestamp in seconds
  • aud — audience (string or array)
  • iss — issuer
  • jti — JWT ID, a unique identifier for the token

Custom claims are anything else you put alongside the standard ones — role, permissions, tenantId, etc. Keep custom claims small; tokens travel in headers and oversized payloads cause real problems.

Key. For HMAC algorithms, this is a string secret; longer is better (32+ random bytes for production HS256). For RSA/ECDSA, it’s a PEM-encoded private key. The verifier needs the matching public material — for HMAC, the same secret; for RSA/ECDSA, the public key paired with the private one.

How signing works

For HS256:

  1. Compute b64h = base64url(JSON(header)).
  2. Compute b64p = base64url(JSON(payload)).
  3. Compute signing_input = b64h + "." + b64p.
  4. Compute sig = HMAC-SHA256(signing_input, secret).
  5. Encode the signature: b64s = base64url(sig).
  6. Concatenate: token = b64h + "." + b64p + "." + b64s.

For RS256, step 4 is RSA-SHA256-Sign(signing_input, private_key) and the rest is identical. For ES256, step 4 is ECDSA-SHA256-Sign and the signature format is the concatenated R || S value (each padded to the curve’s coordinate size).

The output is one URL-safe string with two dots separating the three segments — the same shape every JWT has.

When a browser-side generator is appropriate

Generating tokens in the browser is for development and testing, not for production identity systems. Two reasons:

  1. The signing key is the trust anchor. If your secret or private key ever ends up in a browser, anyone who can XSS your origin or read your devtools can mint tokens. Production token issuance always happens server-side.
  2. The point of signing is verification by a separate party. A token signed by code that runs on the same machine as the verifier doesn’t add security; it just adds steps.

What this tool is good for:

  • Generating test fixtures with specific exp, iat, or custom-claim shapes for unit tests.
  • Reproducing an HS256 token your backend issued (same secret, same payload serialization) to check the signature step.
  • Verifying that a downstream service handles a malformed or expired token correctly.
  • Learning the signing flow without setting up a backend.

Common pitfalls

  • alg: none. The JWT spec includes none as an algorithm, intended for unsigned tokens. Some verifier libraries historically accepted tokens with alg: none even when the issuer signed with HS256 — letting attackers forge tokens by changing the header. Never accept alg: none in production. Pin the expected algorithm in the verifier and reject mismatches.
  • HMAC with a guessable secret. A short HMAC secret is brute-forceable offline. For HS256, use 32+ random bytes encoded as base64 or hex.
  • Mixing up algorithm families. Verifying an HS256 token with an RSA public key (or vice versa) is a known confusion attack — some libraries treat the public key bytes as an HMAC secret. Always verify with the matching algorithm and key type, and check the algorithm against an allowlist.
  • Long-lived tokens. A token with exp 30 days from now is a 30-day exposure if it’s stolen. Short access-token lifetimes (5-15 minutes) plus refresh-token rotation is the standard mitigation.
  • Including secrets in the payload. The payload is base64url-encoded, not encrypted. Anything in it is readable.

The generator above is for development and testing — production token issuance belongs server-side with proper key custody. To inspect a token’s contents (your own or a third party’s), see the JWT decoder.