@lacspace/jwt
v1.2.1
Published
JSON Web Tokens (HS256/384/512) with strict expiry/issuer/audience checks + secure random & CSRF tokens. Isomorphic over Web Crypto — Node, edge, browser.
Maintainers
Readme
@lacspace/jwt
JSON Web Tokens (HMAC) + secure random tokens — done safely.
Sign and verify HS256 / HS384 / HS512 JWTs over Web Crypto with strict expiry / not-before / issuer / audience checks and constant-time signature comparison. Isomorphic — runs on edge and workers where the
jsonwebtokenpackage can't. Plus opaque and CSRF tokens.
- 🎟️
sign/verify/decodewith typed claims - ⏱️
exp/nbf/iat,issuer,audience,clockTolerance - 🧯 Typed
JwtErrorwith acode(expired,signature,audience…) - 🎲
randomToken/csrfToken - ⚡ Zero deps (bar
@lacspace/crypto) · 🌍 isomorphic · fully typed
Install
npm install @lacspace/jwtUsage
import { sign, verify, JwtError } from "@lacspace/jwt";
const token = await sign({ sub: "user_1", role: "admin" }, process.env.JWT_SECRET!, {
expiresIn: 3600, // seconds
issuer: "lacspace",
});
try {
const payload = await verify(token, process.env.JWT_SECRET!, { issuer: "lacspace" });
payload.sub; // "user_1"
} catch (e) {
if (e instanceof JwtError) console.log(e.code); // "expired" | "signature" | …
}Opaque & CSRF tokens
import { randomToken, csrfToken } from "@lacspace/jwt";
randomToken(); // 43-char URL-safe (32 bytes) — session ids, reset tokens
csrfToken(); // CSRF tokenAPI
| Export | Description |
| --- | --- |
| sign(payload, secret, opts?) | algorithm, expiresIn, issuer, audience, subject |
| verify(token, secret, opts?) | throws JwtError; checks sig + claims |
| decode(token) | header + payload, no verification |
| randomToken(bytes?) / csrfToken() | secure random tokens |
The Lacspace Security Kit
| Package | For |
| --- | --- |
| @lacspace/crypto | AES encryption & hashing |
| @lacspace/password | Password hashing |
| @lacspace/jwt | JWTs & tokens (this package) |
| @lacspace/apikey | API keys |
| @lacspace/otp | TOTP/HOTP 2FA |
| @lacspace/webauthn | Passkeys / biometric |
| @lacspace/mfa | 2FA/3FA orchestration |
| @lacspace/lock | Account lockout |
| @lacspace/headers | Secure headers / CSP |
| @lacspace/redact | Log redaction |
New in 1.1 — framework adapters & cookies
import { authenticate, extractBearer, toAuthCookie, clearAuthCookie, expressJwt } from "@lacspace/jwt";
// Verify straight from a Fetch Request / Next route / Node req (Bearer or cookie)
const payload = await authenticate(req, secret); // throws JwtError on failure
const payload2 = await authenticate(req, secret, { cookieName: "session" });
// Hardened auth cookie (HttpOnly + Secure + SameSite by default)
res.headers.set("Set-Cookie", toAuthCookie(token, { name: "session", maxAge: 3600 }));
res.headers.set("Set-Cookie", clearAuthCookie({ name: "session" })); // logout
// Express: verifies the token → req.user, else 401
app.use(expressJwt(secret));New in 1.2 — RS256/ES256, JWKS & refresh tokens
import { sign, verify, importPkcs8, importSpki, createRemoteJWKS, issueTokenPair, rotateRefreshToken } from "@lacspace/jwt";
// Asymmetric: sign with a private key, verify with the public key (clients can't forge)
const priv = await importPkcs8(PRIVATE_PEM, "ES256");
const token = await sign({ sub: "u1" }, priv, { algorithm: "ES256", keyId: "k1" });
// Consume 3rd-party OIDC tokens (Auth0/Cognito/Google) via cached JWKS
const jwks = createRemoteJWKS("https://issuer/.well-known/jwks.json");
const claims = await verify(idToken, jwks, { algorithms: ["RS256"] });
// Refresh-token flow with rotation + reuse detection
const { accessToken, refreshToken, refreshJti } = await issueTokenPair({ sub: "u1" }, secret);
const next = await rotateRefreshToken(refreshToken, secret, { isUsed: (jti) => store.has(jti) });
store.add(next.usedJti); // mark the old one spentPlus audience: string[] matching and importJwk().
Licensing
This package is free under the Lacspace Free Licence — MIT-equivalent freedoms. Use it in personal and commercial projects at no cost; just keep the notice.
Not every Lacspace package is free. We also offer Commercial (paid), Client-specific, and Private (proprietary) packages under separate terms. See the full Lacspace Licence Centre.
Part of the Lacspace ecosystem — 35 zero-dependency, isomorphic TypeScript packages.
