WebCrypto-based Iron Implementation

2.0.0 · active · verified Tue Apr 21

iron-webcrypto is a JavaScript/TypeScript library providing a WebCrypto API-based implementation of `@hapi/iron`. It enables sealing (encrypting and signing) and unsealing JSON-like data using symmetric key encryption with built-in message integrity verification, producing compact, URL-safe string tokens. The current stable version is 2.0.0, which notably dropped support for Node.js versions older than 20 and transitioned to an ESM-only module. It differentiates itself by relying solely on standard WebCrypto APIs, making it highly portable across modern JavaScript runtimes like Node.js v20+, Deno, Bun, and Cloudflare Workers, without depending on Node.js-specific `node:crypto` or `node:buffer` modules. The library's API is designed to be compatible with `@hapi/iron`, facilitating migrations or consistent usage patterns across projects. It ships with full TypeScript type definitions and is primarily intended for server-side or worker environments due to security implications of client-side secret exposure, which could expose encryption secrets.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates sealing a JSON object into a tamper-evident, encrypted token and then unsealing it, highlighting the use of a secure password and default options.

import * as Iron from 'iron-webcrypto'

async function runCryptoExample() {
  // It's crucial to use a strong, randomly generated secret stored securely
  // in environment variables or a secrets manager. NEVER hardcode in production.
  const password = process.env.IRON_SECRET_KEY ?? 'a_long_random_secret_please_change_me_32_chars_min'
  
  if (password.length < 32) {
    console.error('Warning: Password must be at least 32 characters long for security.')
    return
  }

  const payload = { userId: 123, scope: ['user'], issuedAt: Date.now() }

  try {
    const sealed = await Iron.seal(payload, password, Iron.defaults)
    console.log('Sealed token:', sealed)

    // Simulate receiving the token later or in another service
    const unsealed = await Iron.unseal(sealed, password, Iron.defaults)
    console.log('Unsealed payload:', unsealed)

    // Example with TTL (Time To Live)
    const optionsWithTTL = { ...Iron.defaults, ttl: 5000 } // 5 seconds expiry
    const sealedWithTTL = await Iron.seal(payload, password, optionsWithTTL)
    console.log('Sealed token with TTL:', sealedWithTTL)

    // Wait for expiry (optional, for demonstration)
    // await new Promise(resolve => setTimeout(resolve, 6000))
    // try {
    //   await Iron.unseal(sealedWithTTL, password, optionsWithTTL)
    // } catch (e) {
    //   console.log('Expected expiry error:', e.message)
    // }

  } catch (error) {
    console.error('Cryptography operation failed:', error)
  }
}

runCryptoExample()

view raw JSON →