JWT Encoder
Create and sign JSON Web Tokens with HS256, HS384, HS512
Header
Payload
Secret Key
Encoded JWT
Your secret key never leaves your browser. All signing happens client-side.
What Is JWT Encoding?
JWT encoding is the process of creating a JSON Web Token — a compact, URL-safe string that carries a set of claims signed with a cryptographic key. The result is a three-part token (header.payload.signature) defined by RFC 7519 that servers can verify without maintaining session state. JWT encoding online lets you build and sign tokens directly in your browser for testing and development.
The header declares the signing algorithm (e.g. HS256) and token type. The payload contains claims — key-value pairs such as the subject (sub), expiration time (exp), and any custom data your application needs. Both parts are serialized as JSON, then base64url-encoded. The signature is computed over the encoded header and payload using a secret key, binding all three segments together.
Unlike session cookies, JWTs are self-contained: the verifier does not need to query a database or call an external service. This makes JWT-based authentication popular in REST APIs, microservices, and single-page applications where stateless authorization reduces latency and simplifies horizontal scaling.
Why Use a JWT Encoder?
Generating JWTs by hand requires base64url encoding, JSON serialization, and HMAC computation. This tool handles all three steps instantly so you can focus on getting the claims right.
JWT Encoder Use Cases
HS256 vs HS384 vs HS512: HMAC Algorithm Comparison
All three algorithms use HMAC (Hash-based Message Authentication Code) with a shared secret. The difference is the underlying hash function, which affects signature length and security margin. For most applications, HS256 provides sufficient security. Choose HS384 or HS512 when compliance requirements (e.g. FIPS-140) mandate a stronger hash or when your tokens carry high-value authorization decisions.
| Algorithm | Hash | Signature | Speed | Typical use |
|---|---|---|---|---|
| HS256 | SHA-256 | 32 B | Fastest | General purpose, default for most libraries |
| HS384 | SHA-384 | 48 B | Fast | Higher security margin, FIPS-140 compliant |
| HS512 | SHA-512 | 64 B | Fast | Maximum HMAC security, large payloads |
Standard JWT Claims Reference
RFC 7519 defines seven registered claims. None are required, but using them correctly improves interoperability and security. The exp claim is especially important — tokens without an expiration are valid indefinitely if the secret is not rotated.
| Claim | Name | Description | Example |
|---|---|---|---|
| iss | Issuer | Who issued the token | "auth.example.com" |
| sub | Subject | Who the token represents | "user-123" |
| aud | Audience | Intended recipient service | "api.example.com" |
| exp | Expiration | Unix timestamp — token invalid after this time | 1717203600 |
| nbf | Not Before | Unix timestamp — token invalid before this time | 1717200000 |
| iat | Issued At | Unix timestamp when the token was created | 1717200000 |
| jti | JWT ID | Unique token identifier for revocation tracking | "a1b2c3d4" |
JWT Encoding in Code
These examples show how to create and sign JWTs programmatically. Each snippet produces a valid HS256-signed token. For production systems, always set the exp claim and use a cryptographically random secret of at least 256 bits.
async function signJWT(payload, secret, alg = 'HS256') {
const header = { alg, typ: 'JWT' }
const enc = new TextEncoder()
// Base64url encode header and payload
const b64url = (obj) =>
btoa(JSON.stringify(obj)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
const h = b64url(header)
const p = b64url(payload)
// Sign with HMAC-SHA256
const key = await crypto.subtle.importKey(
'raw', enc.encode(secret),
{ name: 'HMAC', hash: 'SHA-256' }, false, ['sign']
)
const sig = await crypto.subtle.sign('HMAC', key, enc.encode(`${h}.${p}`))
const s = btoa(String.fromCharCode(...new Uint8Array(sig)))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
return `${h}.${p}.${s}`
}
// Usage
const token = await signJWT(
{ sub: 'user-123', name: 'Alice', iat: Math.floor(Date.now() / 1000) },
'your-256-bit-secret'
)
// → "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOi..."import jwt
import time
payload = {
"sub": "user-123",
"name": "Alice",
"iat": int(time.time()),
"exp": int(time.time()) + 3600, # expires in 1 hour
}
# Sign with HS256 (default)
token = jwt.encode(payload, "your-256-bit-secret", algorithm="HS256")
# → "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOi..."
# Verify and decode
decoded = jwt.decode(token, "your-256-bit-secret", algorithms=["HS256"])
# → {"sub": "user-123", "name": "Alice", "iat": 1717200000, "exp": 1717203600}const jwt = require('jsonwebtoken')
const payload = {
sub: 'user-123',
name: 'Alice',
role: 'admin',
}
// Sign — iat is added automatically
const token = jwt.sign(payload, 'your-256-bit-secret', {
algorithm: 'HS256',
expiresIn: '1h', // sets exp claim
issuer: 'auth.example.com', // sets iss claim
})
// Verify
const decoded = jwt.verify(token, 'your-256-bit-secret')
// → { sub: 'user-123', name: 'Alice', role: 'admin', iat: ..., exp: ... }package main
import (
"fmt"
"time"
"github.com/golang-jwt/jwt/v5"
)
func main() {
claims := jwt.MapClaims{
"sub": "user-123",
"name": "Alice",
"iat": time.Now().Unix(),
"exp": time.Now().Add(time.Hour).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
signed, _ := token.SignedString([]byte("your-256-bit-secret"))
fmt.Println(signed)
// → eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOi...
}