JWT HS256 Encoder (Client-Side)

Build and HMAC-sign a JWT token in your browser

Construct and HMAC-SHA256-sign a JWT from a custom header, payload, and secret — entirely client-side via the Web Crypto API. Your secret never leaves the browser. Free, keyless JWT encoder for developers. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

Does my secret get sent to a server?

No. Signing runs entirely in your browser using the Web Crypto API (crypto.subtle.sign). The secret, header, and payload never leave the page, which makes this safe for testing real keys.

Sign a JWT without leaving your browser

A JSON Web Token (JWT) is three base64url-encoded parts joined by dots: a header, a payload of claims, and a signature. This tool builds all three from JSON you control and signs them with HS256 — HMAC using SHA-256 — using a secret you provide. Everything happens client-side through the browser’s Web Crypto API, so your secret is never transmitted. It is built for developers debugging auth flows, crafting test fixtures, or learning exactly how a JWT is assembled.

How it works

A JWT is computed as:

header_b64    = base64url(JSON header)
payload_b64   = base64url(JSON payload)
signing_input = header_b64 + "." + payload_b64
signature     = base64url( HMAC_SHA256(secret, signing_input) )
token         = signing_input + "." + signature

The alg field in the header is forced to HS256 so the declared algorithm always matches the signature that is actually computed — a common source of “invalid signature” bugs. Base64url is standard base64 with + replaced by -, / replaced by _, and trailing = padding stripped. The HMAC step uses crypto.subtle.sign with the UTF-8 bytes of your secret as the key.

Tips and notes

Common payload claims include sub (subject), iat (issued-at, a Unix timestamp), and exp (expiry). Remember that a JWT is signed, not encrypted — anyone can base64url-decode the payload and read it, so never put secrets in the claims. To verify the token elsewhere, use the exact same secret string. If a verifier rejects your token, check that the secret matches byte-for-byte and that no extra whitespace crept into the JSON.

What to put in the payload

A minimal payload for a user authentication token typically looks like this:

{
  "sub": "user-abc123",
  "iat": 1735603200,
  "exp": 1735689600,
  "iss": "https://auth.example.com",
  "aud": "api.example.com"
}
  • sub is the subject — the unique identifier for the user in your system.
  • iat is the issued-at time in Unix seconds (Math.floor(Date.now() / 1000) in JavaScript).
  • exp is the expiry time. A common value is iat + 3600 for a one-hour token.
  • iss identifies your auth service.
  • aud names the API or service that should accept the token.

Never include passwords, credit card numbers, or other sensitive data in the payload. The payload is only base64url-encoded, not encrypted — any holder of the token can read it in plain text.

Typical uses for this tool

Writing tests. When you need a JWT with specific claims for a unit or integration test — an expired token, a token for a specific user ID, a token with a particular role — this tool lets you build it precisely without spinning up your auth server.

Learning the JWT format. Editing the JSON header and payload directly and watching the resulting token update teaches you how the three segments relate to each other. Changing one character in the payload changes the signature entirely, demonstrating that the HMAC covers both segments.

Debugging “invalid signature” errors. If a verifier rejects a token you have constructed manually, building the same token here with the same secret lets you compare the expected signature against what your code produces.

Verifying the output

The token produced by this tool can be verified with any standard JWT library by passing the same secret:

// Node.js example using jsonwebtoken
const jwt = require('jsonwebtoken');
const payload = jwt.verify(token, 'your-secret-here');

You can also paste the token into the companion JWT Decoder to confirm the header and payload decoded correctly before using it in tests.