npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@awesome-lang-auth/node

v1.10.8

Published

Database-agnostic JWT authentication and communication bus for Node.js

Readme

awesome-node-auth

npm version license github stars

NPM

A production-ready, database-agnostic JWT authentication library for Node.js written in TypeScript. Drop-in auth for Express, NestJS, Next.js, Fastify and any other Node.js framework — connect to any database through a single interface.

The self-hosted alternative to Supertokens and Supabase Auth. Same enterprise-grade features, zero vendor lock-in.


Installation

npm install @awesome-lang-auth/node

Up to 1.10.0 the package was published as awesome-node-auth. To migrate, replace the dependency with @awesome-lang-auth/node and change your imports from 'awesome-node-auth' to '@awesome-lang-auth/node'; the API is the same.

Quick Start

import express from 'express';
import { AuthConfigurator, AuthEventBus } from '@awesome-lang-auth/node';
import { myUserStore } from './my-user-store'; // your IUserStore impl

const app = express();
app.use(express.json());

const eventBus = new AuthEventBus();

const auth = new AuthConfigurator(
  {
    accessTokenSecret: process.env.ACCESS_TOKEN_SECRET!,
    refreshTokenSecret: process.env.REFRESH_TOKEN_SECRET!,
    accessTokenExpiresIn: '15m',
    refreshTokenExpiresIn: '7d',
  },
  myUserStore,
  { eventBus },
);

app.use(auth.buildAllRouters({
  admin: {
    accessPolicy: 'is-admin-flag', // admin panel for users with isAdmin: true
  },
})); // mounts /auth/* and /auth/admin/*

// Grant the admin panel from a seed script or CLI task (sets isAdmin; needs IUserStore.update):
//   await auth.promoteToAdmin(userId, { method: 'flag' });

app.get('/protected', auth.middleware(), (req, res) => {
  res.json({ user: req.user });
});

app.listen(3000);

Implement IUserStore once for your database and you're done.
Full DB examples (MongoDB, PostgreSQL, MySQL, in-memory) → README.detailed.md.


Features

| Area | Highlights | |---|---| | Auth strategies | Email/password · OAuth 2.0 (Google, GitHub, custom with return_path validation & HMAC state binding) · Magic links · SMS OTP · TOTP 2FA | | Token management | HttpOnly-cookie or Bearer mode · automatic access/refresh rotation · __Host-/__Secure- cookie prefixes | | Identity Provider (IdP) mode (v1.9) | RS256-signed JWTs · public JWKS endpoint (/.well-known/jwks.json) · Resource Server middleware · zero new dependencies | | Stateful sessions (v1.5) | ISessionStore + real-time revocation (checkOn: allcalls\|refresh\|none) · works behind your own L1/L2 cache layers | | Dynamic email templates (v1.6) | ITemplateStore — per-language mail templates + UI i18n with safe hardcoded fallback · built-in MemoryTemplateStore | | CSRF protection | Double-submit cookie pattern · __Host- prefix hardening against cookie-tossing | | Account management | Registration · change email/password · account deletion (onBeforeDeleteUser hook) · email verification (none/lazy/strict + server API/admin trigger) | | Account linking | Link multiple OAuth providers · conflict resolution via IPendingLinkStore | | RBAC | IRolesPermissionsStore with tenant awareness | | Multi-tenancy | ITenantStore for isolated tenant apps | | Admin panel | Full-featured admin UI: user management, sessions, roles, tenants, metadata, API keys, webhooks | | Built-in UI | Zero-dependency HTML/CSS/JS login UI served at <apiPrefix>/ui/ · headless mode for SPAs | | Client libraries | Angular · Flutter · React · served auth.js — see Ecosystem | | Event-driven | AuthEventBus · SSE push · inbound/outbound webhooks · telemetry | | API keys | M2M bcrypt-hashed keys with scopes, expiry, IP allowlist and audit log | | OpenAPI / Swagger | Auto-generated specs for auth, admin and tools routers |


Identity Provider (IdP) Mode (v1.9)

Turn any Provisioner into a central IdP that issues RS256-signed JWTs. Downstream Resource Servers validate tokens via the public JWKS endpoint — no shared secrets.

Generate the RSA private key for your .env (uses Node.js built-in crypto — no install needed):

node -e "
const { generateKeyPairSync } = require('crypto');
const { privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 });
const pem = privateKey.export({ type: 'pkcs8', format: 'pem' });
console.log('IDP_PRIVATE_KEY=' + Buffer.from(pem).toString('base64'));
"

Then in your config:

// Provisioner (IdP)
const auth = new AuthConfigurator({
  accessTokenSecret: '...',
  refreshTokenSecret: '...',
  idProvider: {
    enabled: true,
    issuer: 'https://auth.myplatform.com',
    privateKey: Buffer.from(process.env.IDP_PRIVATE_KEY!, 'base64').toString('utf8'),
  },
}, userStore);

// Resource Server (downstream)
import { createJwksAuthMiddleware } from '@awesome-lang-auth/node';

app.use('/api', createJwksAuthMiddleware({
  jwksUrl: 'https://auth.myplatform.com/.well-known/jwks.json',
  issuer:  'https://auth.myplatform.com',
}), myApiRouter);

In development, if you omit privateKey an ephemeral keypair is auto-generated at startup.

→ Full guide: awesomenodeauth.com/docs/advanced/idp-mode


Key Endpoints

POST   /auth/login              POST /auth/refresh           GET  /auth/me
POST   /auth/register           POST /auth/logout            GET  /auth/sessions        ← device list
POST   /auth/forgot-password    POST /auth/change-password   DELETE /auth/sessions/:h   ← revoke device
POST   /auth/magic-link/send    POST /auth/2fa/verify        DELETE /auth/account
GET    /auth/oauth/:provider    GET  /auth/oauth/:provider/callback
POST   /auth/sessions/cleanup   POST /auth/add-phone         PATCH /auth/profile
GET    /.well-known/jwks.json                                                            ← IdP mode only

Optional Stores Snapshot

const auth = new AuthConfigurator(
  { ...config, templateStore }, // ITemplateStore — dynamic email templates + UI i18n (v1.6), part of AuthConfig
  userStore,
  { eventBus },                 // optional; the third argument only accepts { eventBus }
);

app.use('/auth', auth.router({
  sessionStore,        // ISessionStore        — stateful sessions + device management
  metadataStore,       // IUserMetadataStore   — arbitrary per-user key/value pairs
  rbacStore,           // IRolesPermissionsStore
  tenantStore,         // ITenantStore
  linkedAccountsStore, // ILinkedAccountsStore — several OAuth providers per user
  pendingLinkStore,    // IPendingLinkStore    — OAuth account-linking conflicts (with linkedAccountsStore)
}));

app.get('/protected', auth.middleware(), handler); // uses the sessionStore passed to router() above (call router() first)

With buildAllRouters(), pass the same stores as auth: { … }; the admin panel takes its own in admin: { … } (see Admin UI).

Full configuration reference → README.detailed.md § Configuration


Cookie Management

Clear auth cookies on demand with TokenService.prototype.clearTokenCookies (there is no standalone clearAuthCookies export):

import { TokenService } from '@awesome-lang-auth/node';

new TokenService().clearTokenCookies(res, authConfig);

Admin UI

Use auth.buildAllRouters({ admin: ... }) to mount both the main auth router and the admin router together. The admin router lives at /auth/admin/*, and jwtSecret is auto-filled from AuthConfig.accessTokenSecret. Set accessPolicy (or a non-empty legacy adminSecret): without either, the admin routes are mounted unprotected and a WARNING is written to stderr. Without accessPolicy, an adminSecret that is present but empty (an unset environment variable, for example) throws a configuration error at startup.

| admin option (AdminOptions) | Unlocks | |---|---| | sessionStore | Sessions tab | | rbacStore | Roles & Permissions tab | | tenantStore | Tenants tab | | userMetadataStore | Metadata section in user detail | | settingsStore | ⚙️ Control tab | | linkedAccountsStore | Linked Accounts column | | apiKeyStore | 🔑 API Keys tab | | webhookStore | 🔗 Webhooks tab | | templateStore | Email & UI tab | | uploadDir (optionally uploadBaseUrl) | Logo upload in branding |


Two login endpoints, two audiences

  • /auth/ui/login — end-user login for your application (built-in UI, ui: { enabled: true })
  • /auth/admin/ — admin panel for operators (its sign-in form posts to /auth/admin/login)

They are intentionally different flows. If you mount the admin UI for operators, keep linking end users to /auth/ui/login.

The admin sign-in form checks the password only, with no second factor, and its session opens the admin console and nothing else. To send operators through the application login and its 2FA flow, set admin.loginPath: '/auth/ui/login' (after signing in they land on /; reopen /auth/admin/). POST /auth/admin/login stays mounted and still accepts the password alone, so block it at your proxy if operators must always pass 2FA.


Ecosystem

awesome-node-auth is the reference server of a family of libraries that port its HTTP API to other runtimes, plus client libraries for that API.

Servers

| Runtime | Repository | Status | |---|---|---| | Node.js | awesome-node-auth (this repo) | npm @awesome-lang-auth/node | | Go | awesome-go-auth | Go module, 0.11.x · 1.0 in progress | | AWS Lambda | awesome-lambda-auth | Preview | | Python | awesome-python-auth | PyPI awesome-python-auth 1.1.0 | | Rust | awesome-rust-auth | Git only (not on crates.io) | | Dart | awesome-dart-auth | Git only (not on pub.dev) |

Clients

| Client | Package | Status | |---|---|---| | Angular | ng-awesome-node-auth | npm · to be renamed @awesome-lang-auth/angular | | Flutter | awesome_node_auth_flutter | pub.dev · to be renamed awesome_flutter_auth | | React | @awesome-lang-auth/react | npm 0.1.0 | | Browser | auth.js | Served by this library at <apiPrefix>/ui/auth.js when ui.enabled is set — see Including auth.js |


Documentation

| Resource | Link | |---|---| | Full reference | README.detailed.md | | Wiki / Guides | awesomenodeauth.com | | Changelog | CHANGELOG.md | | Demo apps | demo/ | | Framework examples | examples/ |

The companion MCP server (awesome-node-auth-mcp-server) has been retired and is no longer available.


License

MIT · © 2026 nik2208 · Sponsor ❤