JWT Generator
Generate JSON Web Tokens with multiple algorithm support and custom claims
Secret key for HMAC algorithms (HS256, HS384, HS512)
Enter your JWT payload as valid JSON
What is a JSON Web Token (JWT)?
A JSON Web Token is a compact, URL-safe string that represents claims transferred between two parties. Defined in RFC 7519, a JWT consists of three Base64URL-encoded segments separated by dots: a header declaring the signing algorithm, a payload containing the claims, and a cryptographic signature binding the two together. The jwt-generator tool focuses on the creation side of this process β selecting the appropriate signing algorithm, configuring claims with correct semantics, and assembling a properly signed token ready for use in authentication flows, API authorization, or inter-service communication.
Unlike the jwt-decoder (which only parses and inspects existing tokens without verifying their authenticity) or the jwt-verifier (which validates signatures against a known key), this tool performs the inverse operation: it takes a set of claims and a signing key, then produces a cryptographically signed token. Understanding token generation is essential for backend developers implementing OAuth 2.0 resource servers, microservice-to-microservice authentication, and stateless session management.
Signing Algorithm Selection: HS256, RS256, and ES256
The algorithm specified in the JWT header (alg field) determines how the signature
is computed and verified. RFC 7518 (JSON Web Algorithms) defines the complete set of allowed
algorithms, but three dominate production usage:
- HS256 (HMAC-SHA-256): A symmetric algorithm where the same secret key is used to both sign and verify the token. Fast and simple β ideal when the token issuer and verifier are the same service or share a secret securely. The secret must be at least 256 bits (32 bytes) for full security. Trade-off: every party that verifies tokens must hold the secret, creating a key distribution problem in distributed systems.
- RS256 (RSA-SHA-256): An asymmetric algorithm using RSA key pairs. The issuer signs with a private key; any consumer can verify with the corresponding public key. This eliminates secret sharing β publish your public key via a JWKS endpoint and any service can validate tokens without possessing signing credentials. RSA keys are large (2048+ bits) and signing is computationally heavier than HMAC, but verification is fast. Preferred for OAuth 2.0 identity providers and multi-tenant systems.
- ES256 (ECDSA P-256 with SHA-256): An asymmetric algorithm based on Elliptic Curve Cryptography. Provides the same separation of signing/verification as RS256 but with significantly smaller keys (256-bit vs 2048-bit RSA) and faster signing operations. Signatures are compact (64 bytes vs 256 bytes for RS256), reducing token size. Increasingly adopted in modern systems, mobile clients, and environments where bandwidth matters.
Choose HS256 when the signer and verifier are the same entity or tightly coupled. Choose RS256 or ES256 when tokens are verified by multiple independent services β the public key can be distributed without risk, while the private key stays isolated on the signing authority.
Claims Configuration: Registered, Public, and Private Claims
The JWT payload carries claims β statements about the subject and metadata controlling token behavior. RFC 7519 defines registered claim names with standardized semantics:
- iss (issuer): Identifies the principal that issued the token. Typically a URL or service identifier (e.g.,
"https://auth.example.com"). Verifiers should reject tokens from unrecognized issuers. - sub (subject): Identifies the principal that is the subject of the token β usually a user ID or service account identifier. Must be unique within the issuer's context.
- aud (audience): Identifies the recipients the token is intended for. A resource server should reject tokens whose
auddoes not include its own identifier, preventing token misuse across services. - exp (expiration time): A NumericDate (Unix timestamp in seconds) after which the token MUST be rejected. Critical for security β tokens without expiration live forever if the signing key is never rotated.
- iat (issued at): A NumericDate indicating when the token was issued. Useful for determining token age and enforcing maximum lifetime policies.
- nbf (not before): A NumericDate before which the token MUST NOT be accepted. Used for pre-issuing tokens that activate at a future time.
- jti (JWT ID): A unique identifier for the token. Enables revocation lists and prevents replay attacks by ensuring each token can only be consumed once.
Beyond registered claims, applications define private claims carrying domain-specific data: roles, permissions, tenant IDs, feature flags, or subscription tiers. Keep payloads minimal β every byte increases token size, network overhead, and storage in cookies or headers. Sensitive data (passwords, credit card numbers) must never appear in JWT payloads because the payload is only Base64URL-encoded, not encrypted.
Token Assembly: From Claims to Signed Output
JWT generation follows a deterministic three-step process defined by RFC 7515 (JSON Web Signature):
-
Header construction: Build a JSON object with
alg(the signing algorithm) andtyp(always"JWT"). Optional fields includekid(key ID) for key rotation support. Base64URL-encode this JSON to produce the first segment. -
Payload construction: Build a JSON object with all configured claims β
registered claims (
iss,sub,exp,iat) plus any custom claims. Computeiatas the current Unix timestamp andexpasiat + lifetime. Base64URL-encode this JSON to produce the second segment. -
Signature computation: Concatenate the encoded header and payload with a dot
separator (
header.payload), then apply the signing algorithm with the secret or private key. Base64URL-encode the resulting signature bytes to produce the third segment.
The final token is the concatenation: encodedHeader.encodedPayload.encodedSignature.
This structure ensures that any modification to the header or payload invalidates the signature,
providing tamper detection without encryption. The token is self-contained β a verifier only needs
the appropriate key (shared secret for HS256, public key for RS256/ES256) to validate authenticity
without contacting the issuer.
Common mistakes during token generation include: using exp in milliseconds instead
of seconds, omitting aud (allowing token reuse across services), choosing overly
long expiration times (hours instead of minutes for access tokens), and including the signing
key in the payload itself.
Security Considerations for Token Generation
Generating JWTs carries direct security implications. A poorly generated token can grant unauthorized access, leak sensitive information, or enable escalation attacks:
-
Never use
"alg": "none"in production. The "none" algorithm produces unsigned tokens that any party can forge. Some libraries acceptalg: noneby default β always enforce algorithm whitelisting on both generation and verification sides. - Key strength matters. HS256 secrets must be at least 256 bits of cryptographically random data. Weak secrets (short strings, dictionary words, predictable values) can be brute-forced offline once an attacker obtains a single valid token.
- Minimize token lifetime. Access tokens should expire in minutes (5-15), not hours. Use refresh tokens (stored securely server-side) for longer sessions. Short-lived tokens limit the damage window if a token is leaked.
-
Validate all claims on the verification side. Generation correctness does not
guarantee security β the verifier must check
exp,iss,aud, and algorithm to prevent token reuse, expired token acceptance, and algorithm confusion attacks.
Code Examples
Generating a signed JWT with HS256 (Node.js, no dependencies)
import { createHmac } from 'node:crypto';
function base64url(input) {
return Buffer.from(input)
.toString('base64')
.replace(/=/g, '')
.replace(/\+/g, '-')
.replace(/\//g, '_');
}
function generateJwt(payload, secret, options = {}) {
const header = {
alg: options.algorithm || 'HS256',
typ: 'JWT',
};
const now = Math.floor(Date.now() / 1000);
const claims = {
iat: now,
exp: now + (options.expiresIn || 3600),
...payload,
};
const encodedHeader = base64url(JSON.stringify(header));
const encodedPayload = base64url(JSON.stringify(claims));
const signingInput = encodedHeader + '.' + encodedPayload;
const signature = createHmac('sha256', secret)
.update(signingInput)
.digest('base64url');
return signingInput + '.' + signature;
}
// Generate a token for a user session
const token = generateJwt(
{ sub: 'user-123', iss: 'https://api.example.com', role: 'admin' },
'your-256-bit-secret-key-here-min-32-chars!',
{ expiresIn: 900 } // 15 minutes
);
console.log(token);
// β eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MDk...Output:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MDkwMDAwMDAsImV4cCI6MTcwOTAwMDkwMCwic3ViIjoidXNlci0xMjMiLCJpc3MiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbSIsInJvbGUiOiJhZG1pbiJ9.abc123...Generating a JWT with RS256 using Web Crypto API (browser)
async function generateRs256Jwt(payload, privateKey) {
const header = { alg: 'RS256', typ: 'JWT' };
const now = Math.floor(Date.now() / 1000);
const claims = { iat: now, exp: now + 3600, ...payload };
const encoder = new TextEncoder();
const encodedHeader = btoa(JSON.stringify(header))
.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
const encodedPayload = btoa(JSON.stringify(claims))
.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
const signingInput = encoder.encode(encodedHeader + '.' + encodedPayload);
const signature = await crypto.subtle.sign(
{ name: 'RSASSA-PKCS1-v1_5' },
privateKey,
signingInput
);
const encodedSignature = btoa(String.fromCharCode(...new Uint8Array(signature)))
.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
return encodedHeader + '.' + encodedPayload + '.' + encodedSignature;
}
// Generate RSA key pair for signing
const keyPair = await crypto.subtle.generateKey(
{ name: 'RSASSA-PKCS1-v1_5', modulusLength: 2048, publicExponent: new Uint8Array([1,0,1]), hash: 'SHA-256' },
true, ['sign', 'verify']
);
const jwt = await generateRs256Jwt(
{ sub: 'service-account', aud: 'https://api.target.com' },
keyPair.privateKey
);Standards & Specifications
- RFC 7519 β JSON Web Token specification β defines the token structure, registered claims, and processing rules
- RFC 7518 (JWA) β JSON Web Algorithms β specifies cryptographic algorithms for JWS signatures including HS256, RS256, and ES256
- RFC 7515 (JWS) β JSON Web Signature β defines the signing and serialization process used to produce JWT signatures
Frequently Asked Questions
What is a JWT generator?
A JWT generator creates JSON Web Tokens by combining a header (algorithm), payload (claims like expiration, issuer, custom data), and a signature using your secret key or private key.
Which signing algorithms are supported?
The tool supports HS256, HS384, HS512 (symmetric HMAC), and RS256, RS384, RS512 (asymmetric RSA). HMAC algorithms use a shared secret; RSA algorithms use a private key.
Is my secret key safe?
Yes. All token generation happens entirely in your browser using the Web Crypto API. Your secret keys and private keys are never transmitted to any server.
Can I set custom claims?
Yes. You can configure standard claims (exp, iat, iss, aud, sub) and add any custom key-value pairs to the payload.