← All projects

issuer-node

  • TypeScript 83.57%
  • HTML 15.45%
  • JavaScript 0.98%
git@gitlab.com:aice-lab/otp/issuer-node.git

Latest release

v0.2.1 ·

README

@aice-lab/otp-issuer

pipeline status coverage report

Magic-link OTP token lifecycle library for the aice-auth ecosystem. Issues short-lived, single-use, opaque tokens; delivers verification URLs via pluggable channel adapters; supplies an anti-prefetch landing handler for the consume step.

@aice-lab/otp-issuer plugs into @aice-lab/auth-issuer via the OtpIssuerPort contract — @aice-lab/auth-issuer calls issueToken during register / add-email-handle / recover-start; the user clicks the link in the email; the landing handler POSTs back to consume and the auth-issuer verifies the resulting claims.

This package is distributed via the aice-lab GitLab npm registry (anonymous public read).

Install

# .npmrc
@aice-lab:registry=https://gitlab.com/api/v4/groups/aice-lab/-/packages/npm/

# project
npm install @aice-lab/otp-issuer

Requires Node.js ≥ 20. Express is an optional peer dep (only needed if you mount the landing handler). better-sqlite3 is bundled for SQLite; install pg separately if you prefer Postgres.

Quickstart (SQLite — default)

import express from 'express';
import {
  OtpIssuer,
  KyselyStore,
  createKyselyFromSqlite,
  createVerifyLandingHandler,
  migrate,
} from '@aice-lab/otp-issuer';

const db = createKyselyFromSqlite('./otp.db');
await migrate(db);

const otpIssuer = new OtpIssuer({
  store: new KyselyStore(db),
  delivery: ...,  // BrevoEmailDelivery, or a custom adapter
  verifyUrlBase: 'http://localhost:4000/auth/verify',
  appName: 'my-app',
});

Postgres variant

For projects already on Postgres, wrap an existing pg.Pool:

import { Pool } from 'pg';
import {
  OtpIssuer,
  KyselyStore,
  createKyselyFromPgPool,
  migrate,
} from '@aice-lab/otp-issuer';

const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const db = createKyselyFromPgPool(pool);
await migrate(db);

const otpIssuer = new OtpIssuer({
  store: new KyselyStore(db),
  delivery: ...,
  verifyUrlBase: 'https://yourapp.com/auth/verify',
  appName: 'YourApp',
});

The pool’s lifecycle stays with the caller — db.destroy() does NOT call pool.end().

Migrating from 0.1.x

  • PostgresStore was removed; construct new KyselyStore(createKyselyFromPgPool(pool)) instead.
  • Tables moved from the otp_issuer.* Postgres schema to bare otp_tokens / otp_schema_meta. Migration 0003 renames automatically on first migrate() against an existing Postgres deployment.
  • revoke(tokenId) now marks the token used (used_at set) rather than deleting the row. After revoke, status() returns 'used' (was 'not_found') and consume() throws OtpTokenAlreadyUsedError (was OtpTokenNotFoundError). Forensic history is preserved.

What ships in v0.2

  • OtpIssuer class — issueToken / consume / revoke / buildVerifyUrl
  • KyselyStore — single storage implementation backed by Kysely, works on both PostgreSQL and SQLite with atomic compare-and-mark-used semantics
  • createKyselyFromSqlite / createKyselyFromPgPool factory functions
  • migrate(db) — dialect-aware Kysely migrations
  • DeliveryAdapter interface — pluggable channel for email/SMS/etc.
  • BrevoEmailDelivery — concrete Brevo email adapter (subpath export, opt-in import)
  • createVerifyLandingHandler — anti-prefetch GET/POST flow that protects against email-scanner pre-consumption
  • Bundled mustache templates in en and bn-BD for 4 purposes (register-email-verify, add-email-verify, recover-start, login-step-up)

Adapters not yet shipped

  • SMS providers (SSL Wireless for Bangladesh, Twilio for international) — land in v0.2 alongside downstream phone-handle verification work.
  • WhatsApp / Viber / other channels — implement DeliveryAdapter in your own package; this library imposes no in-tree adapter restriction.
  • Self-hosted SMTP — revisit when your sender domain has reputation.

License

Source: FSL-1.1-Apache-2.0 (see LICENSE and LICENSE.FAQ.md).

Documentation

Architecture: ARCHITECTURE.md.

Contributing

See CONTRIBUTING.md. TDD required; every code change ships with a corresponding test commit. DCO sign-off on every commit (git commit -s).

Reporting security issues

See SECURITY.md. Do not open public issues for vulnerabilities.

This is a snapshot generated from GitLab. For the live README, see the project page.