A secure and tested json-web-token class-based utility library for generating keys, signing, verifying, and decoding JWT payloads for use with your high-security demanding projects.
- β¨ Features
- π₯ Installation
- π Quick Start
- β Usage
- π Quick Docs
- π‘οΈ Supported Algorithms
- π Links
- ποΈ Thanks, Stay Safe and Enjoy
- π― JWT sign and verify with HMAC, ECDSA, RSA, RSA-PSS algorithms.
- ποΈ Easy key generation support.
- β»οΈ Synchronous by default, with asynchronous alternatives.
- β Time helper functions from @bepalo/time.
- π Written in modern TypeScript.
- π’ Available for both ESM and CommonJS.
- π’ Works with Node, Bun, and Deno.
- π’ Built on the crypto API.
Node.js / Bun (npm / pnpm / yarn)
bun add @bepalo/jwt
# or
pnpm add @bepalo/jwt
# or
npm install @bepalo/jwt
# or
yarn add @bepalo/jwt
Deno
Import directly using the URL:
import { JWT } from "npm:@bepalo/jwt";
// or
import { JWT } from "jsr:@bepalo/jwt";
Simple Symmetric HMAC:
import { JWT } from "@bepalo/jwt";
// 1. Generate a key
const secret = JWT.genHmac("HS256");
// 2. Store the generated key somewhere safe like in a .env file
console.log(secret);
// 3. Load that key from where it was stored
const signKey = process.env.SECRET;
const verifyKey = process.env.SECRET;
// 4. Create a JWT instance for signing
const jwtSign = JWT.createSymmetric(signKey, "HS256");
// 5. Sign a payload
const token = jwtSign.signSync({
userId: 123,
role: "admin",
jti: "tid-1234",
iat: JWT.now(),
// exp: JWT.on("2026"),
// nbf: JWT.after(5).Minutes,
// ...
});
// 6. Create another JWT instance for verifying. *optional*
const jwtVerify = JWT.createSymmetric(verifyKey, "HS256");
// 7. Verify and decode the token
const { valid, payload, error } = jwtVerify.verifySync(token, {
jti: "tid-1234",
nbfLeeway: JWT.for(5).Seconds
});
// 8. Deal with errors or use the payload
console.log(valid); // true
console.log(payload); // { userId: 123, role: "admin", ... }
console.log(error); // undefined
Generic:
import { JWT } from "@bepalo/jwt";
// 1. Generate a key
const key = JWT.genKey("ES256");
// 2. Store the generated key somewhere safe like in a .env file
const { alg, publicKey, privateKey } = key;
console.log(JSON.stringify({ alg, publicKey }));
console.log(JSON.stringify({ alg, privateKey }));
// 3. Load that key from where it was stored
const signKey = JSON.parse(process.env.PRIVATE_KEY ?? "null");
const verifyKey = JSON.parse(process.env.PUBLIC_KEY ?? "null");
// 4. Create a JWT instance for signing
const jwtSign = JWT.create(signKey);
// 5. Sign a payload
const token = jwtSign.signSync({
userId: 123,
role: "admin",
jti: "tid-1234",
iat: JWT.now(),
// exp: JWT.on("2026"),
// nbf: JWT.after(5).Minutes,
// ...
});
// 6. Create a JWT instance for verifying
const jwtVerify = JWT.create(verifyKey);
// 7. Verify and decode the token
const { valid, payload, error } = jwtVerify.verifySync(token, {
jti: "tid-1234",
nbfLeeway: JWT.for(5).Seconds
});
// 8. Deal with errors or use the payload
console.log(valid); // true
console.log(payload); // { userId: 123, role: "admin", ... }
console.log(error); // undefined
import { JWT } from "@bepalo/jwt";
// π’ Symmetric HMAC key generation. returns string
const secret = JWT.genHmac("HS256");
// π’ Generic way of generating any key. returns JwtKey
const key = JWT.genKey("none");
const key = JWT.genKey("HS512");
const key = JWT.genKey("ES384");
const key = JWT.genKey("RS256");
const key = JWT.genKey("PS256");
import { JWT } from "@bepalo/jwt";
type Payload = { userId: number, role: "admin" | "user" };
const secret = JWT.genHmac("HS256");
// π’ Symmetric only way of creating a JWT instance.
const jwt = JWT.createSymmetric<Payload>(secret, "HS256");
const key = JWT.genKey("ES256");
// π’ Generic way of creating a JWT instance
const jwt = JWT.create<Payload>(key);
Synchronous:
import { JWT } from "@bepalo/jwt";
type Payload = { userId: number, role: "admin" | "user" };
const key = JWT.genKey("HS256");
const jwt = JWT.create<Payload>(key);
// π’ Sign synchronously
const token = jwt.signSync({ userId: 123, role: "admin", iat: JWT.now() });
Asynchronous:
import { JWT } from "@bepalo/jwt";
type Payload = { userId: number, role: "admin" | "user" };
const key = JWT.genKey("HS256");
const jwt = JWT.create<Payload>(key);
// π’ Sign asynchronously
const token = await jwt.sign({ userId: 123, role: "admin", iat: JWT.now() });
Synchronous:
import { JWT } from "@bepalo/jwt";
type Payload = { userId: number, role: "admin" | "user" };
const key = JWT.genKey("HS256");
const jwt = JWT.create<Payload>(key);
const token = jwt.signSync({ userId: 123, role: "admin", iat: JWT.now() });
// π’ Verify synchronously
const { valid, payload, error } = jwt.verifySync(token);
// π’ Verify signature synchronously
const { valid, error } = jwt.verifySignatureSync(token);
Asynchronous:
import { JWT } from "@bepalo/jwt";
type Payload = { userId: number, role: "admin" | "user" };
const key = JWT.genKey("HS256");
const jwt = JWT.create<Payload>(key);
const token = await jwt.sign({ userId: 123, role: "admin", iat: JWT.now() });
// π’ Verify asynchronously
const payload = await jwt.verify(token);
// π’ Verify signature asynchronously
const valid = await jwt.verifySignature(token);
import { JWT } from "@bepalo/jwt";
type Payload = { userId: number, role: "admin" | "user" };
const key = JWT.genKey("HS256");
const jwt = JWT.create<Payload>(key);
const token = await jwt.sign({
userId: 123,
role: "admin",
iat: JWT.now(),
nbf: JWT.after(5).Minutes,
exp: JWT.on("2026"),
jti: "jti-1234",
iss: "auth-server",
sub: "session",
aud: ["auth-client-a", "auth-client-b"],
});
const payload = await jwt.verify(token, {
strict: false, // default: true
iss: "auth-server",
aud: "auth-client-a", // or ["auth-client-a", "auth-client-c"]
sub: "session",
jti: "jti-1234",
exp: true, // default: true
nbf: false, // default: true
expLeeway: JWT.for(5).Seconds,
nbfLeeway: JWT.for(5).Seconds,
});
const valid = await jwt.verifySignature(token, { strict: false });
All errors thrown or returned by this library are instances of
JwtError
with a descriptive message and a smart error code.
JWT class
// Using Time and RelativeTime for fluent time expression feature.
import type { Time, RelativeTime } from "@bepalo/time";
/**
* JWT class providing utility function and methods to generate keys, and sign, verify and decode tokens.
*/
class JWT<Payload> {
// Get the current time in seconds.
static now(): number;
// Get the given date-time in seconds.
static on(date): number;
// Fluently define absolute time in seconds.
// eg. `JWT.for(1).Day`
static for(): Time;
// Fluently define the relative time in seconds.
// eg. `JWT.in(10).Hours`
static in(): RelativeTime;
// Fluently define the relative time in seconds.
// eg. `JWT.after(5).Minutes`
static after(): RelativeTime;
// Fluently define the relative time in seconds.
// eg. `JWT.before(1).Week`
static before(): RelativeTime;
// Generate a random key for HMAC
static genHmac(alg): string;
// Generate a generic jwt key based on algorithm and optional parameters
static genKey(alg, options?): Key;
// Create a JWT instance using a symmetric algorithm.
static createSymmetric<Payload>(secret, alg): JWT<Payload>;
// Create a JWT instance using an asymmetric JwtKey.
static createAsymmetric<Payload>(key): JWT<Payload>;
// Create a JWT instance using a generic JwtKey.
static create<Payload>(key): JWT<Payload>;
// Synchronously sign a payload and return a JWT token string.
signSync(payload): string
// Asynchronously sign a payload and return a JWT token string.
sign(payload): Promise<string>
// Synchronously verify only the token and the signature (no payload or claims are checked).
verifySignatureSync(token, verifyJwtStrict?): JwtResult<Payload>
// Asynchronously verify only the signature of the token (no claims checked).
verifySignature(token, verifyJwtStrict?): Promise<boolean>;
// Synchronously verify a token, signature, payload and claims.
verifySync(token, verifyJwt?): JwtResult<Payload>;
// Asynchronously verify a token, signature, payload and claims.
verify(token, verifyJwt?): Promise<JwtPayload<Payload>>;
}
JWT Error class
/**
* Error class for use with this JWT library
*/
class JwtError extends Error {
code: JwtErrorCode;
}
JWT Result type
/**
* JWT verify result type
*/
type JwtResult<Payload> = {
valid: boolean;
payload?: JwtPayload<Payload>;
error?: JwtError;
};
JWT Key type
/**
* JWT Key type
*/
type JwtKey = {
alg: JwtAlgorithm,
publicKey: string;
privateKey: string
};
JWT Verify Options type
/**
* Optional parameters for verifying a JWT.
*/
type JwtVerifyOptions = {
// Decoded algorithm must match the stored algorithm. default: true
strict?: boolean;
// Expected issuer
iss?: string;
// Expected audience/s
aud?: string | string[];
// Expected subject
sub?: string;
// Expected token id
jti?: string;
// Enable/disable expiration time check. default: true
exp?: boolean;
// Enable/disable not-before time check. default: true
nbf?: boolean;
// Leeway in seconds for expiration time
expLeeway?: number;
// Leeway in seconds for not-before time
nbfLeeway?: number;
};
JWT Algorithm types
// Supported symmetric algorithms
type JwtSymmetricAlgorithm = "HS256" | "HS384" | "HS512";
// Supported asymmetric algorithms
type JwtAsymmetricAlgorithm =
| "RS256"
| "RS384"
| "RS512"
| "ES256"
| "ES384"
| "ES512"
| "PS256"
| "PS384"
| "PS512";
// All supported JWT algorithms
type JwtAlgorithm =
| JwtSymmetricAlgorithm
| JwtAsymmetricAlgorithm
| "none";
JWT Error codes
/**
* Smart Error codes for use with this JWT library
*/
enum JwtErrorCode {
internalError = 0,
invalid = 100,
tokenInvalid = 110,
tokenTypeInvalid = 111,
tokenHeaderInvalid = 120,
algorithmInvalid = 130,
algorithmMismatch = 131,
signatureInvalid = 140,
signatureMismatch = 141,
payloadInvalid = 150,
// for use with your custom validation errors
claimInvalid = 200,
claimMismatch = 201,
jti = 210,
jtiMismatch = 210,
jtId = 210,
jtIdMismatch = 210,
iss = 220,
issMismatch = 220,
issuer = 220,
issuerMismatch = 220,
sub = 230,
subMismatch = 230,
subjet = 230,
subjectMismatch = 230,
aud = 240,
audMismatch = 240,
audience = 240,
audienceMismatch = 240,
exp = 250,
expired = 250,
nbf = 260,
notValidYet = 260,
notYetValid = 260,
notBefore = 260,
keyInvalid = 300,
privateKeyInvalid = 301,
publicKeyInvalid = 302,
};
π The
ES512
(P-521
) algorithm is less common and might not be supported on the runtime of your preference. But you can useES256
orES384
, or switch to a runtime that supports it.
HMAC-Based (Symmetric, Fast): Used for shared-key authentication.
- HS256: Most common and secure.
- HS384: Slightly stronger but less common.
- HS512: High-security option for robust applications.
ECDSA-Based (Asymmetric, Efficient): Faster than RSA, great for modern applications.
- ES256: Recommended alternative to RSA.
- ES384: Stronger cryptographic security.
- ES512: Best for ultra-secure environments. NOTE: May not be supported/implemented in all runtimes.
RSA-Based (Asymmetric): Used for OAuth, OpenID, and other key-based authentication.
- RS256: Widely used.
- RS384: Stronger but heavier.
- RS512: Computationally expensive but highly secure.
RSA-PSS (Asymmetric): RSA-PSS variants.
- PS256: RSA-PSS variant with SHA-256.
- PS384: RSA-PSS variant with SHA-384.
- PS512: RSA-PSS variant with SHA-512.
For more details, see RFC 7519 and IANA JWT Algorithms.
If you like this library and want to support then please give a star on GitHub
Fund me so I can give more attention to the products and services you liked.