◇ Security & Cryptography

JWT Generator & Signer (HS256, HS384, HS512)

Create and sign JSON Web Tokens with HS256/384/512 for testing APIs — claim helpers for iat, exp, nbf and jti, secret encoding options, and warnings for common mistakes.

HS256 / HS384 / HS512 Claim helpers Secret never stored Open in decoder

Loading JWT Generator…

What this page sends

  • Your input: The secret stays in page memory: it is not saved, not put in a link and not sent anywhere. "Open in decoder" passes only the signed token, in the URL fragment, which browsers do not send to the server.
  • Page load: Loading the page requests HTML, scripts and images from ByteKiln, fonts from Google Fonts, and sends Google Analytics page views, tool-usage events and catalog interactions (tool/category IDs, result status and whether a click followed search — never your input, output or search terms). Privacy & sharing

How the JWT Generator & Signer (HS256, HS384, HS512) Works

When I'm testing an API that expects a bearer token, I rarely want to stand up the real identity provider just to get one. A locally signed JWT with the right claims is enough — as long as it's signed exactly the way the API expects. This generator builds the token from a header and a payload you can edit as JSON, signs it with HMAC-SHA256, 384 or 512 using the browser's Web Crypto API, and colour-codes the three parts of the result. Buttons set iat to now, exp to a preset lifetime, nbf, and a random jti. It checks the things that make APIs reject test tokens: numeric dates in milliseconds instead of seconds, exp earlier than iat or already past, a missing exp, and secrets shorter than the algorithm requires. The secret can be interpreted as UTF-8 text, Base64 or Base64URL, which is the most common reason a token that "should" work fails verification. The output is checked in the test suite against tokens produced by the jsonwebtoken library, and "Open in decoder" hands the token — never the secret — to the JWT decoder through the URL fragment.

Building the token

The header and payload are parsed (comments and trailing commas are tolerated), serialized as compact JSON, and Base64URL-encoded without padding. The header always starts with the selected alg and a typ of JWT unless you set one; other fields such as kid are kept.

Signing

The signing input is header.payload in ASCII. It is signed with HMAC using SHA-256, SHA-384 or SHA-512 via crypto.subtle, and the signature is Base64URL-encoded. The key bytes come from the secret as UTF-8, Base64 or Base64URL.

Claim checks

iat, exp and nbf must be numbers of seconds. The generator warns when one looks like milliseconds, when exp is before iat or in the past, when nbf is in the future, and when there is no exp at all.

Privacy

Nothing is persisted or shared. "Open in decoder" puts only the token in the URL fragment, which browsers never send to a server, and the decoder removes it from the address bar after reading it.

Limitations

  • HMAC only: HS256, HS384 and HS512. RS256 and ES256 tokens need a private key and aren't generated here, and JWE (encrypted tokens) isn't supported.
  • It signs whatever you write; it doesn't know your API's required claims, audience or issuer.
  • Tokens are for testing. Don't use a production signing secret in any web page, including this one.
  • The kid header is just a label here; nothing looks up a key by it, so make sure your API is configured with the same secret you typed.

FAQ

Short answers for the things developers usually ask before trusting a tool.

Is my secret sent anywhere?

No. Tokens are signed with your browser's Web Crypto API. The secret is kept only in the page's memory — it is never saved to storage, never included in a link, and not sent to a server. The page has no share button for that reason.

Why does my API say the signature is invalid?

The most common cause is secret encoding: many frameworks treat the configured secret as Base64, others as plain text. The same characters give different key bytes, so the signature differs. Switch "Secret is" between Text and Base64 to match your server. Other causes are signing with the wrong algorithm and a secret with trailing whitespace.

How long should an HS256 secret be?

At least 32 bytes (256 bits). RFC 7518 requires an HMAC key at least as long as the hash output, and libraries such as jose and .NET's Microsoft.IdentityModel reject shorter keys. The generator warns when the secret is too short for the chosen algorithm.

Are exp and iat in seconds or milliseconds?

Seconds. JWT uses NumericDate: seconds since 1970-01-01T00:00:00Z. A 13-digit value is almost certainly milliseconds from Date.now(), and the generator warns about it.

Can I create a token with alg: none?

Only after ticking an explicit checkbox, and with a warning. An unsigned token can be forged by anyone, so servers must reject it; it is useful only for testing that yours does.

Does it support RS256 or ES256?

Not yet — this version signs with HMAC (HS256, HS384, HS512). To inspect or verify RS256/ES256 tokens, use the JWT decoder, which verifies RSA and ECDSA signatures against a JWK.

Related tools

Useful follow-ups when one conversion usually turns into three more.