Low-level JWT toolkit built on the Web Crypto API. Sign, verify, encrypt, decrypt, and manage keys — JWS, JWE, and JWK in a single zero-dependency package.
📖 Documentation — unjwt.s94.dev
- JWS (RFC 7515) — HMAC, RSA, RSA-PSS, ECDSA, EdDSA. Compact + General/Flattened JSON Serialization (multi-signature).
- JWE (RFC 7516) —
dir, AES-KW, AES-GCM-KW, RSA-OAEP, PBES2, ECDH-ES. AES-GCM and AES-CBC-HMAC-SHA2 content encryption. Compact + General/Flattened JSON Serialization (multi-recipient). - JWK (RFC 7517) — generate, import, export, wrap, unwrap.
CryptoKey↔ JWK ↔ PEM conversion. ECDH-ES shared-secret derivation. JWKS fetching, lookup, and rotation. - Framework adapters — cookie-based JWT sessions for H3 v1 (Nuxt v4 / Nitro v2) and H3 v2 (Nuxt v5 / Nitro v3).
- Runtime-agnostic — Node 22+, Deno, Bun, Cloudflare Workers, browsers. Anywhere Web Crypto runs.
- Zero runtime dependencies for core; optional peer deps for adapters (
h3,cookie-es,rou3).
# Auto-detect package manager (npm, yarn, pnpm, deno, bun)
npx nypm install unjwtAgent skill for Claude Code (and compatible harnesses):
npx skills add sandros94/unjwt// Sign and verify a JWT (JWS)
import { sign, verify } from "unjwt/jws";
import { generateJWK } from "unjwt/jwk";
const key = await generateJWK("HS256");
const token = await sign({ sub: "user_1" }, key, { expiresIn: "1h" });
const { payload } = await verify(token, key);
// { sub: "user_1", iat: ..., exp: ... }
// Encrypt and decrypt (JWE)
import { encrypt, decrypt } from "unjwt/jwe";
const jwe = await encrypt({ secret: "data" }, "my-password");
const { payload: p } = await decrypt(jwe, "my-password");Full walkthroughs, recipes, and the complete API reference live at unjwt.s94.dev:
- Getting started →
- JWS — signing and verifying →
- JWE — encrypting and decrypting →
- JWK — key management →
- H3 session adapters →
- Examples → — authentication, JWKS endpoints, refresh tokens, end-to-end encryption, signed receipts.
local development
Originally visioned by Johann Schopplich, heavily inspired by Filip Skokan's jose internal cryptographic primitives, and initially sponsored by JAMflow — thanks to all three for making this project possible.
Published under the MIT license.
Made by community 💛
🤖 auto updated with automd