Koder JWT
Twórz i podpisuj JSON Web Tokens za pomocą HS256, HS384, HS512
Nagłówek
Ładunek
Klucz tajny
Zakodowany JWT
Twój klucz tajny nigdy nie opuszcza przeglądarki. Całe podpisywanie odbywa się po stronie klienta.
Czym jest kodowanie JWT?
Kodowanie JWT to proces tworzenia JSON Web Token — kompaktnego, bezpiecznego dla adresu URL ciągu zawierającego zestaw oświadczeń podpisanych kluczem kryptograficznym. Wynikiem jest trójczęściowy token (nagłówek.ładunek.podpis) zdefiniowany w RFC 7519, który serwery mogą weryfikować bez utrzymywania stanu sesji.
Nagłówek deklaruje algorytm podpisywania (np. HS256) i typ tokenu. Ładunek zawiera claims — pary klucz-wartość, takie jak podmiot (sub), czas wygaśnięcia (exp) oraz dowolne dane niestandardowe potrzebne aplikacji. Obie części są serializowane jako JSON, a następnie kodowane w formacie base64url. Podpis jest obliczany na podstawie zakodowanego nagłówka i ładunku przy użyciu klucza tajnego, wiążąc wszystkie trzy segmenty razem.
W odróżnieniu od sesyjnych ciasteczek JWT są samowystarczalne: weryfikator nie musi odpytywać bazy danych ani wywoływać zewnętrznej usługi. To sprawia, że uwierzytelnianie oparte na JWT jest popularne w REST API, mikroserwisach i aplikacjach jednostronicowych, gdzie bezstanowa autoryzacja zmniejsza opóźnienia i upraszcza skalowanie poziome.
Po co używać kodera JWT?
Ręczne generowanie JWT wymaga kodowania base64url, serializacji JSON i obliczania HMAC. To narzędzie wykonuje wszystkie trzy kroki natychmiastowo, dzięki czemu możesz skupić się na poprawnym ustawieniu claims.
Przypadki użycia kodera JWT
HS256 vs HS384 vs HS512: porównanie algorytmów HMAC
Wszystkie trzy algorytmy używają HMAC (Hash-based Message Authentication Code) z kluczem wspólnym. Różnica tkwi w funkcji skrótu, która wpływa na długość podpisu i margines bezpieczeństwa. Dla większości zastosowań HS256 zapewnia wystarczające bezpieczeństwo. Wybierz HS384 lub HS512, gdy wymagania zgodności (np. FIPS-140) wymagają silniejszego skrótu lub gdy tokeny zawierają decyzje autoryzacyjne o wysokiej wartości.
| Algorytm | Skrót | Podpis | Szybkość | Typowe zastosowanie |
|---|---|---|---|---|
| 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 |
Informacje o standardowych claims JWT
RFC 7519 definiuje siedem zarejestrowanych claims. Żaden nie jest wymagany, ale ich poprawne stosowanie poprawia interoperacyjność i bezpieczeństwo. Claim exp jest szczególnie ważny — tokeny bez czasu wygaśnięcia są ważne bezterminowo, jeśli klucz tajny nie jest rotowany.
| Claim | Nazwa | Opis | Przykład |
|---|---|---|---|
| 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" |
Kodowanie JWT w kodzie
Te przykłady pokazują, jak programowo tworzyć i podpisywać JWT. Każdy fragment kodu tworzy prawidłowy token podpisany HS256. W systemach produkcyjnych zawsze ustawiaj claim exp i używaj kryptograficznie losowego klucza tajnego o długości co najmniej 256 bitów.
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...
}