@codeimplants/authkit
v1.0.5
Published
Reusable authentication module for Node.js with OTP, JWT, and role-based authorization.
Maintainers
Readme
🔐 Auth Package
A comprehensive, production-ready authentication package for Node.js applications with full TypeScript support and multiple authentication methods including OTP, JWT, and role-based authorization.
✨ Features
- 🔑 JWT Authentication - Access and refresh token management
- 📧 Email/Password Authentication - Traditional email and password login with bcrypt encryption
- 📱 Phone OTP - SMS-based one-time password verification
- 📧 Email OTP - Email-based verification (ready for integration)
- 🔒 Role-based Authorization - Flexible permission system
- 🍪 Cookie-based Tokens - Secure token storage
- 🔄 Automatic Token Refresh - Seamless session management
- ⚡ Express Middleware - Easy integration with Express apps
- 📝 Input Validation - Built-in request validation
- 🛡️ Security Features - Rate limiting, secure cookies, environment-based configs
- 📘 Full TypeScript Support - Complete type definitions and IntelliSense
🚀 Quick Start
Installation
npm install @codeimplants/authkitBasic Usage (JavaScript)
import express from 'express';
import mongoose from 'mongoose';
import { AuthManager } from '@codeimplants/authkit';
// Define your User model
const userSchema = new mongoose.Schema({
name: String,
phoneNumber: { type: String, unique: true },
userRole: { type: String, default: 'user' },
// ... other fields
});
const User = mongoose.model('User', userSchema);
// Initialize Auth Manager
const authManager = new AuthManager({
User,
jwtAccessSecret: process.env.JWT_ACCESS_SECRET,
jwtRefreshSecret: process.env.JWT_REFRESH_SECRET,
otpUrl: process.env.OTP_URL,
otpApiKey: process.env.OTP_API_KEY,
otptemplate: process.env.OTP_TEMPLATE,
});
// Set up routes
app.post('/send-register-otp', authManager.validators.validateSendOtp, authManager.controllers.otp.sendRegisterOTP);
app.post('/send-login-otp', authManager.validators.validateSendOtp, authManager.controllers.otp.sendLoginOTP);
app.post('/verify-otp', authManager.validators.validateVerifyOtp, authManager.controllers.otp.verifyOtp);
// Email OTP routes
app.post('/send-email-otp', authManager.controllers.emailOtp.sendEmailOtp);
app.post('/verify-email-otp', authManager.controllers.emailOtp.verifyEmailOtp);
app.post('/refresh-token', authManager.controllers.auth.refreshAccessToken);
app.post('/logout', authManager.controllers.auth.logoutUser);
// Protected route
app.get('/profile', authManager.middleware.protect, (req, res) => {
res.json({ user: req.user });
});TypeScript Usage
import express from 'express';
import mongoose from 'mongoose';
import AuthManager, { IUser } from '@auth-poc/auth-package';
// Define your User model with TypeScript
interface UserDocument extends mongoose.Document {
name: string;
email: string;
phoneNumber: string;
userRole: 'user' | 'admin';
isVerified: boolean;
isEmailVerified: boolean;
otp?: string;
otpExpires?: Date;
emailOtp?: string;
emailOtpExpires?: Date;
refreshToken?: string;
}
const userSchema = new mongoose.Schema<UserDocument>({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
phoneNumber: { type: String, required: true, unique: true },
userRole: { type: String, default: 'user', enum: ['user', 'admin'] },
isVerified: { type: Boolean, default: false },
isEmailVerified: { type: Boolean, default: false },
otp: String,
otpExpires: Date,
emailOtp: String,
emailOtpExpires: Date,
refreshToken: String,
}, { timestamps: true });
const User = mongoose.model<UserDocument>('User', userSchema);
// Initialize Auth Manager with full type safety
const authManager = new AuthManager({
User,
jwtAccessSecret: process.env.JWT_ACCESS_SECRET!,
jwtRefreshSecret: process.env.JWT_REFRESH_SECRET!,
otp: {
ttl: 5,
length: 6,
retryLimit: 3,
},
jwt: {
accessExpiresIn: '15m',
refreshExpiresIn: '7d',
},
security: {
nodeEnv: process.env.NODE_ENV || 'development',
},
otpUrl: process.env.OTP_URL,
otpApiKey: process.env.OTP_API_KEY,
otptemplate: process.env.OTP_TEMPLATE,
// Email OTP configuration with Nodemailer
email: {
provider: 'nodemailer',
fromEmail: process.env.FROM_EMAIL || '[email protected]',
nodemailer: {
host: process.env.SMTP_HOST || 'smtp.gmail.com',
port: parseInt(process.env.SMTP_PORT || '587'),
secure: process.env.SMTP_SECURE === 'true',
auth: {
user: process.env.SMTP_USER!,
pass: process.env.SMTP_PASS!
},
service: process.env.SMTP_SERVICE || 'gmail'
}
}
});
// Auth routes
const authRouter = express.Router();
// Phone OTP routes
authRouter.post('/send-register-otp',
authManager.validators.validateSendOtp,
authManager.controllers.otp.sendRegisterOTP
);
authRouter.post('/send-login-otp',
authManager.validators.validateSendOtp,
authManager.controllers.otp.sendLoginOTP
);
authRouter.post('/verify-otp',
authManager.validators.validateVerifyOtp,
authManager.controllers.otp.verifyOtp
);
// Email OTP routes
authRouter.post('/send-email-otp',
authManager.controllers.emailOtp.sendEmailOtp
);
authRouter.post('/verify-email-otp',
authManager.controllers.emailOtp.verifyEmailOtp
);
// Protected route with full type safety
authRouter.get('/profile',
authManager.middleware.protect,
(req: any, res) => {
const user = req.user as IUser; // Fully typed user object
res.json({
user: {
_id: user._id,
name: user.name,
email: user.email,
phoneNumber: user.phoneNumber,
userRole: user.userRole,
isVerified: user.isVerified,
isEmailVerified: user.isEmailVerified,
}
});
}
);📋 Configuration Options
Required Configuration
{
User: mongoose.Model, // Your Mongoose User model
jwtAccessSecret: string, // Secret for access tokens
jwtRefreshSecret: string, // Secret for refresh tokens
}Optional Configuration
{
// OTP Configuration
otp: {
ttl: 5, // OTP time-to-live in minutes
length: 6, // OTP length
retryLimit: 3, // Maximum retry attempts
retryDelay: 60, // Delay between retries (seconds)
},
// JWT Configuration
jwt: {
accessExpiresIn: '15m', // Access token expiration
refreshExpiresIn: '7d', // Refresh token expiration
},
// Security Configuration
security: {
nodeEnv: 'development', // Environment
cookieSecure: false, // Secure cookies (auto-set based on env)
cookieSameSite: 'Lax', // SameSite cookie attribute
},
// OTP Service Configuration
otpUrl: string, // OTP service URL
otpApiKey: string, // OTP service API key
otptemplate: string, // OTP template name
// Email Configuration (for Email OTP)
email: {
provider: 'nodemailer', // Email provider: 'nodemailer', 'sendgrid', 'aws-ses'
fromEmail: '[email protected]',
nodemailer: {
host: 'smtp.gmail.com', // SMTP host
port: 587, // SMTP port
secure: false, // true for 465, false for other ports
auth: {
user: '[email protected]',
pass: 'your-app-password'
},
service: 'gmail' // Optional: service name
}
},
// Rate Limiting Configuration
rateLimit: {
otpWindowMs: 5 * 60 * 1000, // 5 minutes
otpMax: 3, // max 3 OTP requests per 5 minutes
passwordWindowMs: 15 * 60 * 1000, // 15 minutes
passwordMax: 5, // max 5 password attempts per 15 minutes
loginWindowMs: 15 * 60 * 1000, // 15 minutes
loginMax: 5, // max 5 login attempts per 15 minutes
registrationWindowMs: 60 * 60 * 1000, // 1 hour
registrationMax: 3, // max 3 registration attempts per hour
},
// Lockout Configuration
lockout: {
otpMaxAttempts: 5, // 5 failed OTP attempts before lockout
otpLockoutDuration: 30 * 60 * 1000, // 30 minutes lockout
passwordMaxAttempts: 3, // 3 failed password attempts before lockout
passwordLockoutDuration: 15 * 60 * 1000, // 15 minutes lockout
loginMaxAttempts: 5, // 5 failed login attempts before lockout
loginLockoutDuration: 30 * 60 * 1000, // 30 minutes lockout
registrationMaxAttempts: 3, // 3 failed registration attempts before lockout
registrationLockoutDuration: 60 * 60 * 1000, // 1 hour lockout
}
}🔧 API Reference
Controllers
Email/Password Controller
registerUser(req: Request, res: Response)- Register new user with email and passwordloginUser(req: Request, res: Response)- Login user with email and passwordchangePassword(req: Request, res: Response)- Change password (authenticated)resetPassword(req: Request, res: Response)- Reset password (unauthenticated)
OTP Controller
sendOtp(req: Request, res: Response)- Send OTP to phone numberverifyOtp(req: Request, res: Response)- Verify OTP and authenticate user
Email OTP Controller
sendEmailOtp(req: Request, res: Response)- Send OTP to emailverifyEmailOtp(req: Request, res: Response)- Verify email OTP and authenticate user
Auth Controller
refreshAccessToken(req: Request, res: Response)- Refresh access token using refresh tokenlogoutUser(req: Request, res: Response)- Logout user and clear tokens
Middleware
Protect Middleware
app.get('/protected', authManager.middleware.protect, (req: any, res) => {
// req.user contains authenticated user with full type safety
const user = req.user as IUser;
res.json({ user });
});Authorization Middleware
app.get('/admin',
authManager.middleware.protect,
authManager.middleware.authorize('admin'),
(req: any, res) => {
const user = req.user as IUser;
res.json({ message: 'Admin access granted', user });
}
);Rate Limiting Middleware
// Rate limiting is automatically disabled in development mode
// Apply rate limiting to sensitive endpoints
// OTP rate limiting (3 attempts per 5 minutes)
app.post('/send-otp',
authManager.rateLimitMiddleware.otpRateLimit,
authManager.validators.validateSendOtp,
controller
);
// Login rate limiting (5 attempts per 15 minutes)
app.post('/login',
authManager.rateLimitMiddleware.loginRateLimit,
authManager.validators.validateLoginUser,
controller
);
// Registration rate limiting (3 attempts per hour)
app.post('/register',
authManager.rateLimitMiddleware.registrationRateLimit,
authManager.validators.validateRegisterUser,
controller
);
// Password rate limiting (5 attempts per 15 minutes)
app.post('/change-password',
authManager.rateLimitMiddleware.passwordRateLimit,
authManager.validators.validateChangePassword,
controller
);
// Registration with lockout protection (3 failed attempts = 1 hour lockout)
app.post('/register',
authManager.lockoutMiddleware.registrationLockout,
authManager.rateLimitMiddleware.registrationRateLimit,
authManager.validators.validateRegisterUser,
controller
);
// Login with lockout protection (5 failed attempts = 30 minutes lockout)
app.post('/login',
authManager.lockoutMiddleware.loginLockout,
authManager.rateLimitMiddleware.loginRateLimit,
authManager.validators.validateLoginUser,
controller
);
// OTP with lockout protection (5 failed attempts = 30 minutes lockout)
app.post('/send-otp',
authManager.lockoutMiddleware.otpLockout,
authManager.rateLimitMiddleware.otpRateLimit,
authManager.validators.validateSendOtp,
controller
);
### Validators
```typescript
// Email/Password validation
app.post('/register', authManager.validators.validateRegisterUser, controller);
app.post('/login', authManager.validators.validateLoginUser, controller);
app.post('/change-password', authManager.validators.validateChangePassword, controller);
app.post('/reset-password', authManager.validators.validateResetPassword, controller);
// Phone OTP validation
app.post('/send-otp', authManager.validators.validateSendOtp, controller);
// OTP verification validation
app.post('/verify-otp', authManager.validators.validateVerifyOtp, controller);
// Email OTP validation
app.post('/send-email-otp', authManager.validators.validateSendEmailOtp, controller);
app.post('/verify-email-otp', authManager.validators.validateVerifyEmailOtp, controller);📱 Authentication Flow
Phone OTP Flow
Send OTP
POST /api/auth/send-otp Content-Type: application/json { "phoneNumber": "+1234567890" }Verify OTP
POST /api/auth/verify-otp Content-Type: application/json { "phoneNumber": "+1234567890", "otp": "123456" }Access Protected Resources
GET /api/profile Cookie: jwt=<access-token>; refreshToken=<refresh-token>
Email OTP Flow
Send Email OTP
POST /api/auth/send-email-otp Content-Type: application/json { "email": "[email protected]" }Verify Email OTP
POST /api/auth/verify-email-otp Content-Type: application/json { "email": "[email protected]", "otp": "123456" }
Email/Password Flow
Register User
POST /api/auth/register Content-Type: application/json { "email": "[email protected]", "password": "securepassword123", "name": "John Doe" }Login User
POST /api/auth/login Content-Type: application/json { "email": "[email protected]", "password": "securepassword123" }Change Password (Authenticated)
POST /api/auth/change-password Content-Type: application/json Cookie: jwt=<access-token> { "currentPassword": "oldpassword", "newPassword": "newsecurepassword123" }Reset Password (Unauthenticated)
POST /api/auth/reset-password Content-Type: application/json { "email": "[email protected]", "newPassword": "newsecurepassword123" }
Token Refresh Flow
POST /api/auth/refresh-token
Cookie: refreshToken=<refresh-token>🛡️ Security Features
- HTTP-Only Cookies: Tokens stored in secure HTTP-only cookies
- Automatic Token Refresh: Seamless token renewal in middleware
- Environment-Based Security: Different security settings for dev/prod
- Input Validation: Built-in request validation using express-validator
- Rate Limiting: Built-in rate limiting for OTP and password endpoints (disabled in development)
- Account Lockout: Automatic account lockout after failed attempts (disabled in development)
- Configurable Limits: Customizable rate limits and lockout thresholds for different authentication methods
🧪 Development
Building the Package
# Install dependencies
npm install
# Build TypeScript to JavaScript
npm run build
# Development mode with watch
npm run dev
# Clean build directory
npm run cleanAvailable Scripts
npm run build- Compile TypeScript to JavaScriptnpm run dev- Watch mode for developmentnpm start- Start production servernpm run lint- Run ESLintnpm run format- Format code with Prettiernpm run docs- Generate documentationnpm run clean- Clean build directory
📝 Environment Variables
Create a .env file:
# JWT Secrets
JWT_ACCESS_SECRET=your-super-secret-access-key
JWT_REFRESH_SECRET=your-super-secret-refresh-key
# OTP Service (for production)
OTP_URL=https://your-otp-service.com/api
OTP_API_KEY=your-otp-api-key
OTP_TEMPLATE=your-otp-template
# App Configuration
NODE_ENV=development
PORT=5000
FRONTEND_URL=http://localhost:3000
# Email Configuration (for Email OTP with Nodemailer)
[email protected]
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
[email protected]
SMTP_PASS=your-app-password
SMTP_SERVICE=gmail🔮 Roadmap
- [ ] Email OTP integration with 2Factor
- [ ] OAuth providers (Google, GitHub, Facebook)
- [ ] Two-factor authentication (2FA)
- [ ] Password-based authentication
- [ ] Account lockout protection
- [ ] Session management
- [ ] Audit logging
- [ ] Enhanced TypeScript types for better IntelliSense
