JWT Encoder
Maak en onderteken JSON Web Tokens met HS256, HS384, HS512
Header
Payload
Geheime sleutel
Gecodeerd JWT
Je geheime sleutel verlaat nooit je browser. Alle ondertekening gebeurt aan de clientzijde.
Wat is JWT-codering?
JWT-codering is het proces van het maken van een JSON Web Token — een compacte, URL-veilige tekenreeks die een set claims bevat die zijn ondertekend met een cryptografische sleutel. Het resultaat is een driedelig token (header.payload.signature) gedefinieerd door RFC 7519 dat servers kunnen verifiëren zonder de sessietoestand in stand te houden.
De header declareert het ondertekeningsalgoritme (bijv. HS256) en het tokentype. De payload bevat claims — sleutel-waardeparen zoals het onderwerp (sub), de vervaltijd (exp) en eventuele aangepaste gegevens die jouw applicatie nodig heeft. Beide delen worden geserialiseerd als JSON en vervolgens base64url-gecodeerd. De signature wordt berekend over de gecodeerde header en payload met een geheime sleutel, waarmee alle drie segmenten aan elkaar worden gekoppeld.
In tegenstelling tot sessiecookies zijn JWT's zelfstandig: de verificateur hoeft geen database te raadplegen of een externe dienst aan te roepen. Dit maakt JWT-gebaseerde authenticatie populair in REST API's, microservices en single-page applicaties waar staatloze autorisatie de latency vermindert en horizontale schaalbaarheid vereenvoudigt.
Waarom een JWT Encoder gebruiken?
JWT's handmatig genereren vereist base64url-codering, JSON-serialisatie en HMAC-berekening. Dit hulpmiddel voert alle drie stappen onmiddellijk uit, zodat je je kunt concentreren op de juiste claims.
Gebruikssituaties voor JWT Encoder
HS256 vs HS384 vs HS512: vergelijking van HMAC-algoritmen
Alle drie algoritmen gebruiken HMAC (Hash-based Message Authentication Code) met een gedeeld geheim. Het verschil zit in de onderliggende hashfunctie, die de lengte van de signature en de veiligheidsmarge beïnvloedt. Voor de meeste toepassingen biedt HS256 voldoende beveiliging. Kies HS384 of HS512 wanneer nalevingsvereisten (bijv. FIPS-140) een sterkere hash voorschrijven of wanneer je tokens beslissingen met hoge autorisatiewaarde bevatten.
| Algoritme | Hash | Handtekening | Snelheid | Typisch gebruik |
|---|---|---|---|---|
| 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 |
Referentie standaard JWT-claims
RFC 7519 definieert zeven geregistreerde claims. Geen enkele is verplicht, maar correct gebruik ervan verbetert de interoperabiliteit en beveiliging. De exp-claim is bijzonder belangrijk — tokens zonder vervaldatum zijn onbeperkt geldig als het geheim niet wordt geroteerd.
| Claim | Naam | Beschrijving | Voorbeeld |
|---|---|---|---|
| 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-codering in code
Deze voorbeelden laten zien hoe je JWT's programmatisch aanmaakt en ondertekent. Elk fragment produceert een geldig HS256-ondertekend token. Stel voor productiesystemen altijd de exp-claim in en gebruik een cryptografisch willekeurig geheim van minimaal 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...
}