Tooleux

JWT Sign

JWT (3)

Create a signed JSON Web Token from a payload. Supports HMAC, RSA, RSA-PSS, ECDSA, and EdDSA.

Runs in your browser. Nothing leaves your device.
Create and sign JSON Web Tokens (JWT) with HS256, HS384, HS512, RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, or EdDSA. Free, offline, runs in your browser. Read more Show less

What is JWT Sign?

A JSON Web Token (JWT) is a compact, URL-safe way to represent claims - statements about a user or a system - that can be verified by a third party. JWTs are used for authentication (every OAuth 2.0 and OpenID Connect flow ends with one), API authorization, session tokens, single sign-on, and passing identity between microservices.

A JWT has three parts separated by dots: header.payload.signature. This tool builds that string from a JSON payload, signs it with the algorithm and key you provide, and shows you the resulting token.

It is the exact inverse of the JWT Decoder - you can sign here, then paste the result there to inspect it.

Anatomy of a JWT

PartContentsEncoded as
Headeralg (algorithm), typ (usually "JWT"), optional kid (key ID)Base64URL of JSON
PayloadClaims - sub, iss, aud, exp, iat, and any custom fieldsBase64URL of JSON
SignatureThe cryptographic proof that the sender holds the keyBase64URL of the raw signature bytes

Anyone can decode a JWT. It is not encrypted. Do not put secrets, passwords, or private data in the payload. The signature proves the token was not modified - it does not hide anything.

Algorithms

HMAC (HS256 / HS384 / HS512) - symmetric. One shared secret both signs and verifies. Fast, simple, secure if the secret is high entropy and never leaks. Use a random string at least 32 bytes long.

RSA PKCS#1 v1.5 (RS256 / RS384 / RS512) - asymmetric. A private key signs; a public key verifies. Use this when multiple services need to verify tokens but only one should be able to create them.

RSA-PSS (PS256 / PS384 / PS512) - a modern alternative to PKCS#1 v1.5 with a randomized padding scheme. Some systems require it. Considered more future-proof than RS*.

ECDSA (ES256 / ES384 / ES512) - asymmetric, much smaller keys and signatures than RSA. ES256 uses P-256, ES384 uses P-384, ES512 uses P-521. Common in modern identity systems.

Never use alg: none. It disables verification entirely. Almost every JWT vulnerability in the wild comes from libraries that accepted none or trusted the algorithm field from the attacker.

How to use

Enter the payload as JSON. The tool validates it and produces a token. Then choose the algorithm and paste your secret (for HS*) or private key in PEM format (for RS*, PS*, ES*).

The token updates live. Click the output to copy the entire token.

For algorithms that require a private key, use a PKCS#8 PEM (-----BEGIN PRIVATE KEY-----). If your key is in PKCS#1 form (-----BEGIN RSA PRIVATE KEY-----), convert it first: openssl pkcs8 -topk8 -nocrypt -in key.pem -out key-pkcs8.pem.

Standard claims

iss - issuer. Who created the token.

sub - subject. Usually the user ID.

aud - audience. Who the token is for.

exp - expiration time, as a Unix timestamp (seconds). The token is invalid after this.

nbf - not before. The token is invalid before this time.

iat - issued at. When the token was created.

jti - JWT ID. A unique identifier, used to prevent replay.

Everything else is a custom claim. Namespace collision is a real risk - for production, prefix custom claims with your own domain or app name.

FAQ

Can I put a password or credit card number in the payload?

No. The payload is Base64URL-encoded, not encrypted. Anyone with the token can read it. If you need encrypted claims, use JWE instead of JWS.

How long should my HMAC secret be?

At least as long as the hash output - 32 bytes for HS256, 48 for HS384, 64 for HS512. Use a cryptographically random string, not a password. You can generate one on the Random Bytes page.

What is the "kid" header for?

Key ID. It tells the verifier which key was used to sign, useful when you rotate keys. It is not a secret and is not itself authenticated - the signature still proves which key actually signed the token.

Why does my signature not verify on another system?

Four common reasons: (1) the token was modified in transit, (2) the verifier used a different key, (3) the algorithm in the header does not match the algorithm the verifier expects, (4) the base64 padding was changed. Copy the exact token, not a trimmed version.

Does this tool upload my secret key?

No. Everything runs in your browser using the Web Crypto API. Nothing is sent anywhere. Your private keys and shared secrets never leave your device.

How long can a token be?

There is no hard limit in the spec, but most HTTP servers cap header size at 8 KB. For a token to fit in an Authorization header, keep the payload small - 10-20 claims is plenty.

What does "alg: none" mean and why is it dangerous?

Some implementations allow a JWT with alg: none and an empty signature, meant for testing. If a library accepts none without explicitly requiring it, an attacker can forge any token. This tool does not offer none as an option.

Can I sign with my existing private key from the RSA Key Generator?

Yes. Generate a key pair on the RSA Key Generator, copy the private key PEM, and paste it here. Use RS256 for maximum compatibility.

Command line equivalent
# Node with jose
npm i jose
node --input-type=module -e '
import { SignJWT } from "jose";
const secret = new TextEncoder().encode("your-256-bit-secret");
const jwt = await new SignJWT({ role: "admin" })
  .setProtectedHeader({ alg: "HS256" })
  .setSubject("1234567890")
  .setIssuedAt()
  .setExpirationTime("1h")
  .sign(secret);
console.log(jwt);
'

# Python with PyJWT
pip install pyjwt
python3 -c '
import jwt
print(jwt.encode({"sub": "1234567890"}, "your-256-bit-secret", algorithm="HS256"))
'

# OpenSSL - manual construction
# 1. base64url(header).base64url(payload)
# 2. openssl dgst -sha256 -hmac "secret" -binary | base64url

# jwt.io - but this tool runs entirely offline
Loads a test value into the form
Payload (JSON)
Signed JWT