Install
$ agentstack add mcp-awesome-lang-auth-awesome-node-auth ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
awesome-node-auth
[](https://github.com/sponsors/nik2208)
[](https://nodei.co/npm/awesome-node-auth/)
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-node-auth
Quick Start
import express from 'express';
import { AuthConfigurator, AuthEventBus } from 'awesome-node-auth';
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](./README.detailed.md).
Features
| Area | Highlights | |---|---| | Auth strategies | Email/password · OAuth 2.0 (Google, GitHub, custom) · 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 · email verification (none/lazy/strict) | | 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 /ui/ · headless mode for SPAs | | Client libraries | Angular · Flutter · React · served auth.js — see [Ecosystem](#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-node-auth';
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](#admin-ui)).
Full configuration reference → [README.detailed.md § Configuration](./README.detailed.md#configuration)
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-node-auth | | 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 /ui/auth.js when ui.enabled is set — see [Including auth.js](./README.detailed.md#including-authjs) |
Documentation
| Resource | Link | |---|---| | Full reference | [README.detailed.md](./README.detailed.md) | | Wiki / Guides | awesomenodeauth.com | | Changelog | [CHANGELOG.md](./CHANGELOG.md) | | Demo apps | [demo/](./demo) | | Framework examples | [examples/](./examples) |
> The companion MCP server (awesome-node-auth-mcp-server) has been retired and is no longer available.
License
[MIT](./LICENSE) · © 2026 nik2208 · Sponsor ❤
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: awesome-lang-auth
- Source: awesome-lang-auth/awesome-node-auth
- License: MIT
- Homepage: https://www.awesomenodeauth.com
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.