Every time I start a new Node.js backend, authentication ends up being the most repetitive and fragile part of the project.
No matter the stack, I keep rewriting the same things:
- User registration flows
- Password hashing with bcrypt
- JWT generation and verification
- Role-based access control
- Database-specific queries baked into auth logic
Even after years of building APIs, auth still feels like copy-paste architecture — slightly different each time, never quite right, and tightly coupled to the database or ORM I’m using.
That frustration is exactly why I built node-auth-kit.
- 👉 npm: https://www.npmjs.com/package/node-auth-kit
- 👉 GitHub: https://github.com/learningyogendra-netizen/device_auth
The “Auth Gap” in the Node.js Ecosystem
The Node.js ecosystem is massive, but authentication usually falls into one of two extremes:
1. The DIY Trap
Libraries like Passport.js are powerful, but very low-level.
They give you strategies — not structure.
You end up with authentication logic scattered across controllers, services, and models.
2. The Black Box Trap
Frameworks and SaaS auth providers work fast — until you need to:
- customize a flow
- migrate your database
- control your data
Then you realize you’re locked in.
If you’ve ever worked with Ruby on Rails, you probably miss Devise:
- strong defaults
- predictable structure
- extensible when needed
I wanted that same Devise philosophy, but for Node.js.
The Core Idea: Database-Agnostic by Design
Most Node.js auth tutorials teach you to bake authentication directly into your ORM models (Mongoose, Prisma, etc.).
This works — until you need to:
- test auth in isolation
- change databases
- reuse logic across projects
node-auth-kit takes a different approach.
It uses an adapter architecture:
- Core engine → handles auth logic (password rules, JWT, roles, hooks)
- Adapters → handle database communication
Your authentication logic stays the same.
Your database can change.
What This Looks Like in Practice
Instead of writing controllers, you configure the auth engine.
import {
deviceAuth,
mongooseAdapter,
createAuthRouter,
} from 'node-auth-kit';
deviceAuth
.init({
authType: 'jwt',
signupFields: ['email', 'password'],
defaultRole: 'user',
token: {
accessTokenTtl: '1h',
},
})
.useAdapter(
mongooseAdapter({
userModel: User,
})
);
Then mount the generated routes:
app.use('/auth', createAuthRouter());
That’s it.
You now have:
- POST /auth/register
- POST /auth/login
- GET /auth/me
Route Protection Without Boilerplate
Protecting routes is just middleware:
import { authenticate, authorize } from 'node-auth-kit';
app.get('/profile', authenticate, (req, res) => {
res.json(req.user);
});
app.get('/admin', authenticate, authorize('admin'), (req, res) => {
res.json({ message: 'Admin access granted' });
});
No duplicated logic.
No custom guards everywhere.
Lifecycle Hooks (The Underrated Feature)
One thing I missed from frameworks was clean extensibility.
node-auth-kit supports lifecycle hooks:
- beforeRegister
- afterRegister
- beforeLogin
- afterLogin
Example:
deviceAuth.registerHook('afterRegister', async (user) => {
// send welcome email, log analytics, etc.
});
Why I Open Sourced It
Authentication is too critical to live as hidden code in private repos.
Every team shouldn’t spend their first 1–2 days rebuilding login systems.
We should be building product features, not re-implementing auth patterns.
node-auth-kit is my attempt to create a shared, opinionated starting point for Node.js authentication.
Current Status & Roadmap
- ✅ JWT authentication
- ✅ Role-based authorization
- ✅ Adapter-based DB support
- ✅ Stable Mongoose adapter
- 🚧 Prisma adapter (in progress)
- 🔜 Refresh tokens
- 🔜 Multi-device sessions
- 🔜 Password reset & email verification
Get Started in Under 60 Seconds
npm i node-auth-kit
- 👉 npm: https://www.npmjs.com/package/node-auth-kit
- 👉 GitHub: https://github.com/learningyogendra-netizen/node-auth-kit
If this saves you time, a ⭐ on GitHub really helps the project grow.
Final Thought
Stop rewriting authentication.
Start building your product.
Top comments (0)