issuer-node
git@gitlab.com:aice-lab/otp/issuer-node.git
Latest release
v0.2.1 ·
README
@aice-lab/otp-issuer
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
PostgresStorewas removed; constructnew KyselyStore(createKyselyFromPgPool(pool))instead.- Tables moved from the
otp_issuer.*Postgres schema to bareotp_tokens/otp_schema_meta. Migration 0003 renames automatically on firstmigrate()against an existing Postgres deployment. revoke(tokenId)now marks the token used (used_atset) rather than deleting the row. After revoke,status()returns'used'(was'not_found') andconsume()throwsOtpTokenAlreadyUsedError(wasOtpTokenNotFoundError). Forensic history is preserved.
What ships in v0.2
OtpIssuerclass —issueToken / consume / revoke / buildVerifyUrlKyselyStore— single storage implementation backed by Kysely, works on both PostgreSQL and SQLite with atomic compare-and-mark-used semanticscreateKyselyFromSqlite/createKyselyFromPgPoolfactory functionsmigrate(db)— dialect-aware Kysely migrationsDeliveryAdapterinterface — 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
enandbn-BDfor 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
DeliveryAdapterin 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.