Encode JWT data into a JWTSIGN output using a fast, client-only JWT encoder that runs directly in your browser.
Token will appear here once you click Sign JWT.
HS256 / HS384 / HS512 (HMAC with a shared secret), RS256 / RS384 / RS512 (RSA private key, PKCS#1 v1.5), ES256 / ES384 / ES512 (ECDSA on P-256 / P-384 / P-521), or EdDSA (Ed25519). HS* is fine for a single monolith; use RS*, ES*, or EdDSA when verifiers are separate services.{"sub":"1234567890","name":"Alice","iat":1716700000,"exp":1716703600}. RFC 7519 registered claims (iss, sub, aud, exp, nbf, iat, jti) plus any custom claims your API expects. Time values are seconds since 1970-01-01 UTC, not milliseconds.-----BEGIN PRIVATE KEY----- (PKCS#8) or -----BEGIN RSA PRIVATE KEY----- (PKCS#1).header.payload.signature (base64url, no padding). Everything happens in your browser — no key ever leaves the tab.JSON Web Tokens are the de-facto bearer credential for REST and GraphQL APIs in 2026 — short, URL-safe, and self-contained so the resource server can authorize a request without a database round-trip. Hand-building one with a CLI means juggling base64url, header JSON, and an OpenSSL command per algorithm; an in-browser encoder turns it into a 30-second loop. Common reasons to mint one yourself:
{"sub":"test-user","role":"admin","exp":...}) to reproduce a 401 in staging without dragging in your full auth flow.exp 60-300 s) RS256 token in one microservice and verify it with the public key in another, no shared secret required.private_key_jwt client authentication (RFC 7523) needs an RS256 or ES256-signed JWT in the token request. Mint one here, paste it as client_assertion.HS256 and RS256 to see how header/signature lengths change, or experiment with the JWT decoder to confirm your token round-trips.| Algorithm | Key type | Signature size | Security (2026) | When to pick it |
|---|---|---|---|---|
| HS256 / HS384 / HS512 | Symmetric secret (HMAC-SHA-2) | 32 / 48 / 64 bytes | Strong if secret ≥ 32 bytes and never shared with verifiers | Single monolith that both signs and verifies |
| RS256 / RS384 / RS512 | RSA 2048-bit+ private key (PKCS#1 v1.5) | 256 bytes (2048-bit key) | Strong; ubiquitous library support | Distributed systems; publish the public key via JWKS |
| PS256 / PS384 / PS512 | RSA 2048-bit+ (RSASSA-PSS) | 256 bytes | Stronger than PKCS#1 v1.5, randomised padding | New systems that need RSA but want modern padding |
| ES256 / ES384 / ES512 | ECDSA P-256 / P-384 / P-521 | 64 / 96 / 132 bytes | Equivalent to RSA-3072 / 7680 / 15360 at 1/40th the size | Cookies, mobile clients, anywhere signature bytes matter |
| EdDSA (Ed25519) | 32-byte Edwards-curve key | 64 bytes | State of the art — deterministic, no nonce-reuse foot-gun | New greenfield services without RSA compatibility need |
| none | (no signature) | 0 bytes | UNSAFE — accepts any forged token | Never. Reject unconditionally on the verifier side. |
Sources: Auth0 — RS256 vs HS256, Scott Brady — Which Signing Algorithm Should I Use?.
| Claim | Name | Type | Notes |
|---|---|---|---|
iss |
Issuer | string / URI | Identifies who minted the token. Verifiers should pin a known value. |
sub |
Subject | string | The principal — usually a user ID. Unique within the issuer. |
aud |
Audience | string OR array of strings | RFC 7519 §4.1.3 allows either; verifier MUST reject if its own identifier isn't in the list. |
exp |
Expiration Time | NumericDate (seconds since epoch, UTC) | After this instant the token MUST be rejected. Use Math.floor(Date.now()/1000)+3600 for "+1 h". |
nbf |
Not Before | NumericDate | Token MUST be rejected if used before this instant. |
iat |
Issued At | NumericDate | When the token was signed. Useful for max-age policies. |
jti |
JWT ID | string | Unique per token. Lets the verifier blacklist or detect replay. |
Use HS256 only when the same single service both signs and verifies — for example a small monolith with one secret in env vars. The moment another service (a microservice, a mobile app, a partner API) needs to verify your tokens, switch to RS256 (or ES256 / EdDSA). With RS* you publish a public key — usually at a JWKS endpoint like /.well-known/jwks.json — and verifiers can validate without you ever sharing the signing material. Auth0, AWS Cognito, Okta, Keycloak, and Firebase Auth all default to RS256 for that reason.
none algorithm?The JWS spec defined alg: "none" for tokens whose integrity is guaranteed by some other channel — but most libraries historically accepted a none-signed token without checking, meaning an attacker could strip the signature, set "alg":"none", and the verifier would treat the forged payload as authentic. The bug class is so common it has its own family of CVEs (e.g. CVE-2021-44878 in pac4j-jwt); algorithm-confusion vulnerabilities are a well-documented risk class across JWT libraries. Real fix: pass an explicit allow-list of algorithms (["RS256"]) to jwt.verify() and reject everything else, including case variants like nOnE. There is no legitimate production use case for unsigned JWTs.
exp — milliseconds or seconds?Seconds since 1970-01-01T00:00:00Z UTC, as a JSON number (RFC 7519 §2 calls this a NumericDate). The classic bug is passing Date.now() directly (milliseconds) — your token then expires roughly in the year 50,000 or fails immediately depending on the verifier. Always use Math.floor(Date.now() / 1000) in JavaScript or int(time.time()) in Python.
aud be an array or only a single string?Both. RFC 7519 §4.1.3 says "In the general case, the aud value is an array of case-sensitive strings... In the special case when the JWT has one audience, the aud value MAY be a single case-sensitive string." Verifiers MUST check that their own identifier appears in the array (or matches the single string). If your token will be consumed by multiple APIs, use an array — "aud":["https://api.example.com","https://reports.example.com"].
ES256 if the signature size matters (cookies, mobile, IoT, JWTs in URLs) — 64 bytes vs RS256's 256. ECDSA on P-256 gives ~128-bit security, equivalent to a 3072-bit RSA key. Caveats: ECDSA requires a high-quality random nonce per signature; reuse leaks the private key (the PlayStation 3 hack). If you don't want to think about that, pick EdDSA (Ed25519) instead — it's deterministic, has no nonce, and is the modern best-practice default. Stick with RS256 only if you need broad library compatibility (e.g. legacy SAML/OIDC ecosystems where some verifiers still don't ship ECDSA).
kid header?kid (Key ID) is an optional JOSE header that names which key signed the token. The verifier looks up that ID in a JWKS (https://your-domain/.well-known/jwks.json) to find the matching public key. During rotation you publish both the old and new keys in the JWKS, start signing new tokens with the new kid, and let existing tokens verify against the old key until they expire. After the longest exp window passes, drop the old key. Without kid, rotation is a hard cutover and any token signed before the swap immediately fails. Add it as {"alg":"RS256","kid":"2026-05-key-1","typ":"JWT"} in the header.
exp be?Depends on the token's job. Access tokens that grant API access should be short — 5 to 60 minutes is typical (Google access tokens are 1 hour, AWS STS defaults to 1 hour). Refresh tokens that mint new access tokens can live longer (days to weeks) but should be opaque server-side records, not JWTs, so they can be revoked. ID tokens (OIDC) usually mirror access-token lifetime. Shorter exp = smaller damage window if a token leaks, but more refresh chatter; tune to your threat model.
HS256 is HMAC-SHA-256, which expects a key at least as long as the hash output — 32 bytes (256 bits) of true entropy. A user-chosen password like "hunter2" has perhaps 20 bits and is trivially brute-forceable offline once an attacker captures one token. Generate with openssl rand -base64 32, crypto.randomBytes(32).toString('base64'), or use the password generator with length 44 (which gives 32 bytes once base64-decoded). For HS384 use 48 bytes, HS512 64 bytes.
No. JWT signing happens entirely in your browser via the Web Crypto API — neither your payload nor your private key ever leaves the tab. Close the page and the key is gone from memory. If you need to inspect a signed token, the JWT decoder is also client-side and read-only. Format your payload first with the JSON formatter if it's compact / minified.