Developer

JWT generator

JWT Generator

Generate JWT tokens with dummy values for testing and development.

Leave empty to use a dummy secret key
Enter valid JSON for custom claims

About JWT Tokens

JWT Structure:

A JWT consists of three parts separated by dots:

  • Header: Contains metadata about the token
  • Payload: Contains the claims (data)
  • Signature: Used to verify the token
Standard Claims:
  • iss (issuer): Who issued the token
  • aud (audience): Who the token is intended for
  • sub (subject): The subject of the token
  • exp (expiration): When the token expires
  • iat (issued at): When the token was issued
Algorithms:
  • HS256/384/512: HMAC with SHA (symmetric)
  • RS256/384/512: RSA with SHA (asymmetric)
Security Note:

This tool generates tokens for testing purposes only. Never use weak secrets in production!

A fixture token is not an identity

I use this page when a local API, a Postman collection, or a Cypress stub needs a JWT that looks real enough to parse. I do not use it to mint anything a customer will hold. Generating a token is not verifying one. The sister decoder will show you the claims; it will not check the HMAC. If your Node app rejects the string, the usual culprits are a different secret, an aud/iss mismatch, or exp in the wrong units — not this page “failing to sign.”

What this is not: a key-management service, a production signer, or a place to paste the HMAC from your cloud secret store. HS256, HS384, and HS512 go through Web Crypto in the tab. The secret still sat in a JavaScript string. Treat that like a notepad. The RS256 / RS384 / RS512 options are demo stubs — they do not import an RSA private key. Tokens from those options will not verify on a real jsonwebtoken or jose stack. Leave them alone.

Worked example: a disposable HS256 fixture

Algorithm HS256. Secret dev-only-not-prod — type it; an empty field falls back to a built-in dummy. Subject qa-user, audience local-api, custom claims {"role":"reader","org":"qa"}. Expiration 1 hour. iat and exp are Unix seconds. Generate, copy the three-segment string, send it to localhost. In the decoder, header.alg should read HS256 and payload.role should read reader. Point the same token at a server whose secret is some-other-dev-key: the signature check fails. That is the whole point of HMAC. Screenshot the token if you must; rotate the secret before the screenshot leaves Slack.

Worked example: exp is seconds, IST is +5:30

Unix 1725000000 is 2024-08-30 06:40:00 UTC, which is 12:10 IST. JWT NumericDate is that integer in seconds, not milliseconds. If you paste a 13-digit value such as 1725000000000 into a custom exp claim, you have dated the token around the year 56,000. Libraries will either reject it as insane or treat it as “never expires for our lifetimes.” I have seen both. India has no daylight-saving shift, so the IST offset is a boring +5:30 all year; the bug is mixing ms and seconds, not DST.

Worked example: custom claims must be JSON

That box is JSON.parse, not a guesser. {role: admin} fails (unquoted keys). {"gstin":"27AAPFU0939F1ZV"} parses, and then you have a tax identifier in a token you will paste into a ticket. Use {"gstin":"TESTGSTIN0000"} for fixtures. Trailing commas fail. Single quotes fail. The generator refuses rather than silently dropping the object — good — but the error is easy to miss if you keep typing in other fields, because generation is debounced on input.

Limits that become incidents

Empty secret → dummy-secret-key-for-testing. Fine for a demo; a surprise if you thought you signed with something from .env. Checking the output JWT into git is how fixtures become production auth. Editing claims here and expecting a live verifier to honor them without sharing the secret is decode-versus-verify confusion again. JWE (encrypted tokens) is a different format; this page emits compact JWS. I will not tell you to paste a production secret. If you already did, rotate it on the server. This tab is not an HSM.

Questions

Why does my local Express app reject a token I just made?

Secret mismatch first. Then aud/iss if those checks are on. Then exp if the clock is wrong or you used milliseconds. Generating here does not mean verifying there.

If I pick RS256, will jose or jsonwebtoken accept it?

No. The RS* path is a truncated stand-in, not RSA with a private key. Use HS* with a disposable secret, or mint RS tokens in your repo with openssl.

Can I put milliseconds in iat or exp?

The spec’s NumericDate is seconds. Around “now,” that is ten digits. Thirteen digits is milliseconds and will look like the far future.

Does generate equal verify?

No. Verification is an HMAC or public-key check with a key you keep on the server. The decoder only base64url-decodes. This page only builds.

What if I leave the secret blank?

You get dummy-secret-key-for-testing. Anyone else who also leaves it blank can forge matching tokens.

Where does the HMAC actually run?

In this tab, via Web Crypto, after you type the secret. That is still a browser page — do not type the production HMAC.

Related tools