Hades Auth

raw JSON →
1.0.63 verified Mon Apr 27 auth: no javascript

Hades Auth is a client-side authentication library (v1.0.63) that uses elliptic-curve cryptography (ECDSA with P-384) for public/private key identity. It provides functions to generate key pairs, onboard devices, sign requests, and wrap fetch calls with signed headers. Unlike token-based auth (JWT/sessions), it never sends secrets to the server; only public keys are stored, making database leaks less catastrophic. The library is ESM-only, ships TypeScript definitions, and is actively released on npm. It is designed for browser use (uses Web Crypto API) and includes a fetch wrapper that automates request signing. The package is maintained by OracularHades.

error Error [ERR_REQUIRE_ESM]: require() of ES Module /path/to/node_modules/hades-auth/src/index.js from /path/to/your/file.js not supported.
cause Using require() on an ESM-only package.
fix
Replace require('hades-auth') with import ... from 'hades-auth' or use dynamic import('hades-auth').
error TypeError: fetch_wrapper is not a function
cause Attempted to use fetch_wrapper as a default or incorrect import. The package exports named exports.
fix
Use import { fetch_wrapper } from 'hades-auth'.
error Uncaught (in promise) TypeError: Failed to execute 'importKey' on 'SubtleCrypto': parameter 2 is not of type 'ArrayBuffer'.
cause Private key or public key passed to sign/onboard is not a valid PEM string or is malformed.
fix
Ensure you are passing the exact string returned by generate_new_credentials or stored properly.
breaking Package is ESM-only. Using require() will cause ERR_REQUIRE_ESM. Must use import or dynamic import().
fix Use import syntax in your project; if you cannot switch to ESM, use dynamic import() with await or promise.
gotcha When using fetch_wrapper with Express and JSON body parser, you must set Content-Type to application/json. Otherwise Express treats body as empty.
fix Explicitly set 'Content-Type': 'application/json' in fetch options when sending JSON.
deprecated No functions are deprecated yet. Always check changelog.
fix N/A
gotcha Private key must be in PEM format as returned by generate_new_credentials. Passing an incorrect format will cause signing to fail silently or throw.
fix Always store and retrieve the private_key string exactly as produced by generate_new_credentials.
npm install hades-auth
yarn add hades-auth
pnpm add hades-auth

Shows full flow: generate key pair client-side, register public key on server via onboard_new_device, store keys, then make signed requests using fetch_wrapper.

import { generate_new_credentials, onboard_new_device, fetch_wrapper } from 'hades-auth';

// Client: generate key pair
async function register() {
  const creds = await generate_new_credentials();
  localStorage.setItem('private_key', creds.private_key);
  // Send public_key to server
  const response = await fetch('/api/register', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ public_key: creds.public_key })
  });
  const { device_id } = await response.json();
  localStorage.setItem('device_id', device_id);
}

// Server: verify public key
// (in an Express-like handler)
app.post('/api/register', async (req, res) => {
  try {
    const verification = await onboard_new_device(req.body.public_key);
    // Store public_key with verification.deviceid (or custom ID)
    res.json({ device_id: verification.deviceid });
  } catch (e) {
    res.status(400).json({ error: 'Invalid key' });
  }
});

// Client: signed request
async function fetchData() {
  const privateKey = localStorage.getItem('private_key');
  const deviceId = localStorage.getItem('device_id');
  const response = await fetch_wrapper('https://api.example.com/data', {
    method: 'GET',
    headers: { 'Content-Type': 'application/json' }
  }, deviceId, privateKey);
  return response.json();
}