π # Device Auth
Device Auth is a Devise-inspired authentication and authorization library for Node.js.
It gives you:
- Config-driven auth (email + password, roles, JWT, password rules)
- Plug-and-play Express routes via
createAuthRouter - JWT-based security with
authenticatemiddleware - Role-based authorization with
authorize - Database-agnostic adapter system (
mongooseAdapter, future Prisma, etc.) - Lifecycle hooks (before/after register/login) for side effects
You bring your framework (Express) and database (Mongo, Prisma, SQL). Device Auth handles the rest.
- β JWT Authentication (Access Tokens)
- π Role-based Authorization
- π§© Adapter Pattern (DB-agnostic)
- π Ready-to-use Express routes via
createAuthRouter - π Secure password hashing
- π¦ Mongoose adapter (Stable)
- π§ͺ Prisma adapter (In progress β V2)
- π§ Inspired by Ruby on Rails Devise
npm i node-auth-kitor
yarn add node-auth-kitnode-auth-kit itself is DB-agnostic. Database drivers / ORMs are optional and only required if you use the corresponding adapter:
- For Mongoose adapter:
mongoose - For Prisma adapter (V2):
@prisma/client
Create a .env file:
MONGO_URL=mongodb://localhost:27017/device-auth
DEVICE_AUTH_JWT_SECRET=your-super-secret-keyimport mongoose from 'mongoose';
const UserSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
},
password: {
type: String,
required: true,
},
role: {
type: String,
enum: ['admin', 'staff', 'user'],
default: 'user',
},
createdAt: {
type: Date,
default: Date.now,
},
});
export const User = mongoose.model('User', UserSchema);import 'dotenv/config';
import express from 'express';
import mongoose from 'mongoose';
import {
deviceAuth,
mongooseAdapter,
createAuthRouter,
authenticate,
authorize,
} from 'node-auth-kit';
import { User } from './models/User';
const app = express();
app.use(express.json());
// 1. Connect MongoDB
mongoose
.connect(process.env.MONGO_URL)
.then(() => console.log('MongoDB connected'))
.catch(console.error);
// 2. Initialize Device Auth
deviceAuth
.init({
authType: 'jwt',
signupFields: ['email', 'password'],
defaultRole: 'user',
password: {
minLength: 8,
requireNumbers: true,
requireSpecialChars: true,
saltRounds: 10,
},
token: {
accessTokenTtl: '15m',
},
})
.useAdapter(
mongooseAdapter({
userModel: User,
}),
);
// 3. Mount Auth Routes
app.use('/auth', createAuthRouter());
// 4. Example Protected Route
app.get(
'/admin',
authenticate,
authorize('admin'),
(req, res) => {
res.json({ message: 'Admin access granted' });
},
);
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});The default router created by createAuthRouter() exposes:
| Method | Endpoint | Description |
|---|---|---|
| POST | /auth/register |
Register new user |
| POST | /auth/login |
Login user |
| GET | /auth/me |
Get current user |
You can mount it under any base path (e.g. /api/auth).
app.use('/auth', createAuthRouter());Validates the JWT from the Authorization: Bearer <token> header and attaches the user to req.user.
app.get('/profile', authenticate, (req, res) => {
res.json(req.user);
});Restricts access based on user role.
app.get('/admin', authenticate, authorize('admin', 'staff'), (req, res) => {
res.json({ message: 'Admin or staff only' });
});Device Auth uses a pluggable adapter architecture, allowing it to work with different databases without changing core logic.
Supported / planned adapters:
| Adapter | Status |
|---|---|
| Mongoose | β Stable |
| Prisma | π§ In Progress (V2) |
| TypeORM | β Planned |
The public exports you can use:
mongooseAdapterβ helper for MongoDB via MongooseMongooseAdapterβ underlying class (advanced use)
The central entry point is deviceAuth:
import { deviceAuth, defaultConfig } from 'node-auth-kit';
deviceAuth.init({
...defaultConfig,
authType: 'jwt',
defaultRole: 'user',
signupFields: ['email', 'password'],
// override anything you need
});Key options:
authType: currentlyjwtsignupFields: required fields on registrationdefaultRole: assigned when no role is providedpassword:minLengthrequireNumbersrequireSpecialCharssaltRounds
token:accessTokenTtl(e.g.15m,1h)
The merged configuration is accessible via:
const config = deviceAuth.config;Hooks let you run side effects around key lifecycle events without forking core logic.
Supported hook names:
beforeRegisterafterRegisterbeforeLoginafterLogin
Register hooks on deviceAuth:
import { deviceAuth } from 'node-auth-kit';
deviceAuth
.registerHook('beforeRegister', async (createData) => {
// e.g. validate extra fields, audit, etc.
})
.registerHook('afterRegister', async (user) => {
// e.g. send welcome email
})
.registerHook('beforeLogin', async (user) => {
// e.g. check if user is blocked
})
.registerHook('afterLogin', async (user) => {
// e.g. log login event
});Hook errors are intentionally swallowed so they never break core auth flow.
Planned for upcoming versions:
- π Refresh tokens
- π± Multi-device sessions
- πͺ Logout (single device / all devices)
- π§ Forgot & reset password
- β Email verification
- π§ͺ Stable Prisma adapter
- π§ Additional hooks & lifecycle events
npm testPostman collection β coming soon.
Contributions are welcome!
-
Fork the repository
-
Create a new branch
git checkout -b feature/my-feature
-
Commit your changes
-
Push to your branch
-
Open a Pull Request
MIT License Β© 2025