Package Exports
- secure-node-auth
- secure-node-auth/src/index.js
- secure-node-auth/src/middleware/FastifyPlugin
- secure-node-auth/src/middleware/FastifyPlugin.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (secure-node-auth) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
๐ Secure Node Auth
Blazing fast, zero-config authentication system with JWT for MySQL & PostgreSQL. Set up secure auth in seconds!
โจ Features
- โก Zero Configuration - Works out of the box with sensible defaults
- ๐๏ธ MySQL & PostgreSQL Support - Choose your preferred database with one line of config
- ๐ Production-Ready Security - Bcrypt hashing, JWT tokens, rate limiting, account lockout
- ๐ง Email Verification - URL-based or 6-digit code verification (new!)
- ๐ Audit Logging - Optional security event logging (customizable)
- ๐ Lightning Fast - Built with connection pooling and optimized queries
- ๐จ Highly Customizable - Add custom fields, hooks, and configurations
- ๐ Auto Schema Setup - Automatically creates tables, indexes, and relationships
- ๐ฏ Express & Fastify Support - Pre-built routes and middleware for both frameworks
- ๐ฆ Refresh Tokens - Secure token rotation with blacklisting
- ๐ก๏ธ Attack Protection - Rate limiting, SQL injection protection, brute force prevention
- ๐ Extensible - Plugin system with before/after hooks
- ๐ TypeScript Support - Full type definitions included
๐ฆ Installation
npm install secure-node-authDependencies:
mysql2orpg- Database client (MySQL or PostgreSQL)jsonwebtoken- JWT token generationbcrypt- Password hashingvalidator- Input validationexpressorfastify- Web framework (peer dependencies)
For MySQL:
npm install secure-node-auth mysql2For PostgreSQL:
npm install secure-node-auth pg๐ Quick Start
MySQL Setup (3 lines!)
const SecureNodeAuth = require('secure-node-auth');
const auth = new SecureNodeAuth({
connection: {
type: 'mysql', // Optional, defaults to MySQL
host: 'localhost',
user: 'root',
password: 'your_password',
database: 'myapp',
},
});
await auth.init(); // Auto-creates tables!
// Use with Express
app.use('/auth', auth.router());PostgreSQL Setup (3 lines!)
const SecureNodeAuth = require('secure-node-auth');
const auth = new SecureNodeAuth({
connection: {
type: 'postgres', // Use PostgreSQL
host: 'localhost',
user: 'postgres',
password: 'your_password',
database: 'myapp',
},
});
await auth.init(); // Auto-creates tables!
// Use with Express
app.use('/auth', auth.router());๐ Complete PostgreSQL Guide - Migration, Docker setup, and advanced features.
That's it! You now have a complete authentication system with:
- โ User registration
- โ Login with JWT
- โ Token refresh
- โ Password change
- โ Profile management
- โ Logout (single/all devices)
๐ Usage Examples
Complete Express Server
require('dotenv').config();
const express = require('express');
const SecureNodeAuth = require('secure-node-auth');
const app = express();
app.use(express.json());
// Initialize auth system
const auth = new SecureNodeAuth({
connection: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
},
});
await auth.init();
// Mount auth routes
app.use('/auth', auth.router());
// Protected route example
app.get('/api/profile', auth.middleware(), async (req, res) => {
const user = await auth.getUserById(req.user.userId);
res.json({ user });
});
app.listen(3000, () => console.log('Server running on port 3000'));Complete Fastify Server
const fastify = require('fastify')({ logger: true });
const SecureNodeAuth = require('secure-node-auth');
const secureNodeAuthPlugin = require('secure-node-auth/src/middleware/FastifyPlugin');
async function start() {
// Initialize auth system
const auth = new SecureNodeAuth({
connection: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
},
});
await auth.init();
// Register auth plugin (includes all routes + middleware)
await fastify.register(secureNodeAuthPlugin, {
authInstance: auth,
routeOptions: {
prefix: '/auth',
},
});
// Protected route example
fastify.get(
'/api/profile',
{
preHandler: fastify.authenticate,
},
async (request, reply) => {
const user = await auth.getUserById(request.user.userId);
return { user };
}
);
await fastify.listen({ port: 3000 });
console.log('๐ Server running on http://localhost:3000');
}
start();๐ Complete Fastify Guide - Detailed Fastify integration, rate limiting, validation, and performance tips.
Adding Custom Fields
โ Recommended: Add fields before initialization
const auth = new SecureNodeAuth({
/* config */
});
// Add custom fields BEFORE init()
auth.addField({
name: 'phoneNumber',
type: 'VARCHAR(20)',
required: false,
unique: true,
});
auth.addField({
name: 'companyName',
type: 'VARCHAR(255)',
required: false,
});
auth.addField({
name: 'subscriptionTier',
type: "ENUM('free', 'premium', 'enterprise')",
defaultValue: 'free',
});
await auth.init();
// Now register with custom fields
await auth.register({
email: 'user@example.com',
password: 'SecurePass123!',
phoneNumber: '+1234567890',
companyName: 'Tech Corp',
subscriptionTier: 'premium',
});โ ๏ธ Advanced: Runtime schema changes (use with caution)
For existing databases, you can add columns after initialization using dangerous methods:
// Already initialized
await auth.init();
// Add single column (โ ๏ธ can cause table locks)
await auth.dangerouslyAddColumn(
{
name: 'phoneNumber',
type: 'VARCHAR(20)',
unique: true,
},
{ confirmed: true }
);
// Add multiple columns with transaction (PostgreSQL)
await auth.dangerouslyMigrateSchema(
[
{ name: 'age', type: 'INTEGER', defaultValue: 0 },
{ name: 'city', type: 'VARCHAR(100)' },
],
{ confirmed: true, useTransaction: true }
);๐ Complete Migration Guide - Safety tips, examples, and best practices.
Using Hooks
// Before/after registration
auth.on('beforeRegister', async (userData) => {
console.log('New user signing up:', userData.email);
// Add custom validation, check blacklist, etc.
});
auth.on('afterRegister', async (result) => {
console.log('User registered:', result.user.email);
// Send welcome email, create user profile, etc.
await sendWelcomeEmail(result.user.email);
});
// Before/after login
auth.on('beforeLogin', async ({ email }) => {
console.log('Login attempt:', email);
});
auth.on('afterLogin', async (result) => {
console.log('Successful login:', result.user.email);
// Track analytics, update last login, etc.
});Manual Authentication Flow
// Register
const { user, tokens } = await auth.register({
email: 'john@example.com',
password: 'SecurePass123!',
firstName: 'John',
lastName: 'Doe',
});
// Login
const login = await auth.login('john@example.com', 'SecurePass123!');
console.log(login.tokens.accessToken);
console.log(login.tokens.refreshToken);
// Verify token
const decoded = await auth.verifyAccessToken(login.tokens.accessToken);
console.log(decoded.userId, decoded.email);
// Refresh access token
const { accessToken } = await auth.refreshToken(login.tokens.refreshToken);
// Change password
await auth.changePassword(userId, 'OldPass123!', 'NewPass456!');
// Logout
await auth.logout(refreshToken);
// Logout all devices
await auth.logoutAll(userId);๐ง Configuration Options
const auth = new SecureNodeAuth({
// Database connection
connection: {
host: 'localhost',
user: 'root',
password: '',
database: 'myapp',
port: 3306,
connectionLimit: 10,
},
// JWT configuration
jwt: {
accessSecret: 'your-access-secret',
refreshSecret: 'your-refresh-secret',
accessExpiresIn: '15m', // 15 minutes
refreshExpiresIn: '7d', // 7 days
},
// Security settings
security: {
bcryptRounds: 10, // Higher = more secure, slower
maxLoginAttempts: 5, // Account lockout threshold
lockoutTime: 900000, // 15 minutes in milliseconds
passwordMinLength: 8,
passwordRequireUppercase: true,
passwordRequireNumbers: true,
passwordRequireSpecialChars: true,
},
// Custom table names
tables: {
users: 'my_users',
refreshTokens: 'my_tokens',
loginAttempts: 'my_login_attempts',
},
});๐ก API Endpoints
When you mount auth.router(), these endpoints are automatically available:
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /register |
Register new user | โ |
| POST | /login |
Login user | โ |
| POST | /refresh |
Refresh access token | โ |
| POST | /logout |
Logout (revoke token) | โ |
| POST | /logout-all |
Logout all devices | โ |
| GET | /me |
Get current user | โ |
| PATCH | /me |
Update user profile | โ |
| POST | /change-password |
Change password | โ |
| POST | /verify |
Verify token | โ |
| GET | /health |
Health check | โ |
Request/Response Examples
Register:
POST /auth/register
{
"email": "user@example.com",
"password": "SecurePass123!",
"firstName": "John",
"lastName": "Doe"
}
// Response
{
"success": true,
"message": "User registered successfully",
"data": {
"user": { ... },
"tokens": {
"accessToken": "eyJhbG...",
"refreshToken": "eyJhbG...",
"expiresIn": "15m"
}
}
}Login:
POST /auth/login
{
"email": "user@example.com",
"password": "SecurePass123!"
}
// Response
{
"success": true,
"message": "Login successful",
"data": {
"user": { ... },
"tokens": { ... }
}
}๐ Complete API Methods
Core Authentication
await auth.init()- Initialize system and create tablesawait auth.register(userData)- Register new userawait auth.login(email, password)- Login and get tokensawait auth.refreshToken(refreshToken)- Get new access tokenawait auth.logout(refreshToken)- Logout single sessionawait auth.logoutAll(userId)- Logout all sessionsawait auth.verifyAccessToken(token)- Verify JWT token
User Management
await auth.getUserById(userId)- Get user by IDawait auth.getUserByEmail(email)- Get user by emailawait auth.updateUser(userId, updates)- Update user dataawait auth.updateProfile(userId, updates)- Update profile (alias)await auth.changePassword(userId, oldPass, newPass)- Change passwordawait auth.getUserCount()- Get total user countawait auth.isAccountLocked(email)- Check if account locked
Email Verification
URL-Based Verification:
await auth.sendVerificationEmail(email, url)- Send verification emailawait auth.verifyEmail(token)- Verify email with tokenawait auth.resendVerificationEmail(email, url)- Resend verification
6-Digit Code Verification (New!):
await auth.sendVerificationCode(email, options)- Send 6-digit codeawait auth.verifyCode(email, code)- Verify with 6-digit code
Utility:
await auth.isEmailVerified(userId)- Check if email verified
๐ก Tip: Use URL verification for web apps, 6-digit codes for mobile apps or better UX. See Verification Guide
Password Reset
URL-Based Reset:
await auth.sendPasswordResetEmail(email, url)- Send reset emailawait auth.resetPassword(token, newPassword)- Reset password
6-Digit Code Reset (New!):
await auth.sendPasswordResetCode(email, options)- Send 6-digit reset codeawait auth.resetPasswordWithCode(email, code, newPassword)- Reset with code
๐ก Tip: Use URL reset for web apps, 6-digit codes for mobile apps. Codes expire in 15 minutes (customizable).
Database Maintenance
await auth.cleanupExpiredTokens()- Clean expired tokensawait auth.cleanupExpiredLoginAttempts(days)- Clean old attemptsawait auth.cleanupRevokedRefreshTokens(days)- Clean revoked tokensawait auth.performMaintenance(options)- Run all cleanupauth.getPool()- Get raw database pool
Schema Customization
auth.addField(config)- Add field before initawait auth.dangerouslyAddColumn(config, options)- Add column at runtimeawait auth.dangerouslyMigrateSchema(fields, options)- Batch migration
Hooks & Integration
auth.on(event, callback)- Register lifecycle hooksauth.router(options)- Get Express/Fastify routerauth.middleware()- Get auth middlewareawait auth.close()- Close database connection
๐ Complete API Reference - Detailed documentation with examples
๐ก๏ธ Security Features
Password Security
- โ Bcrypt hashing (configurable rounds)
- โ Minimum length requirements
- โ Complexity requirements (uppercase, numbers, special chars)
- โ Common password blacklist
Account Protection
- โ Brute force protection (rate limiting)
- โ Account lockout after failed attempts
- โ Automatic lockout expiration
- โ Login attempt tracking
Token Security
- โ Separate access and refresh tokens
- โ Short-lived access tokens (15m default)
- โ Token revocation support
- โ Logout from all devices
- โ Automatic token cleanup
Database Security
- โ Parameterized queries (SQL injection protection)
- โ Connection pooling
- โ Indexed queries for performance
- โ Foreign key constraints
๐๏ธ Database Schema
The package automatically creates these tables:
secure_auth_users
- id (PRIMARY KEY)
- email (UNIQUE, INDEXED)
- password (HASHED)
- firstName
- lastName
- emailVerified
- isActive
- createdAt
- updatedAt
+ your custom fieldssecure_auth_refresh_tokens
- id (PRIMARY KEY)
- userId (FOREIGN KEY)
- token
- revoked
- expiresAt (INDEXED)
- createdAtsecure_auth_login_attempts
- id (PRIMARY KEY)
- email (INDEXED)
- success
- ipAddress
- userAgent
- attemptedAt๐ฃ Hooks System
Available hooks:
beforeRegister- Before user registrationafterRegister- After successful registrationbeforeLogin- Before login attemptafterLogin- After successful loginbeforeTokenRefresh- Before token refreshafterTokenRefresh- After token refresh
auth.on('afterRegister', async (result) => {
// Your custom logic
await sendWelcomeEmail(result.user.email);
await createUserProfile(result.user.id);
});๐ Middleware Usage
// Protect single route
app.get('/api/protected', auth.middleware(), (req, res) => {
console.log(req.user); // { userId, email, iat, exp }
res.json({ message: 'Protected data' });
});
// Protect multiple routes
app.use('/api', auth.middleware());
// Custom role-based middleware
const requireAdmin = async (req, res, next) => {
const user = await auth.getUserById(req.user.userId);
if (user.role !== 'admin') {
return res.status(403).json({ error: 'Admin access required' });
}
next();
};
app.get('/api/admin', auth.middleware(), requireAdmin, (req, res) => {
res.json({ message: 'Admin only' });
});๐งช Testing
# Install dependencies
npm install
# Run example server
npm run example
# The server will start on http://localhost:3000Test endpoints with curl:
# Register
curl -X POST http://localhost:3000/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"SecurePass123!"}'
# Login
curl -X POST http://localhost:3000/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"SecurePass123!"}'๐ Advanced Topics
Environment Variables
Create a .env file:
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=myapp
DB_PORT=3306
JWT_ACCESS_SECRET=your_super_secret_access_key
JWT_REFRESH_SECRET=your_super_secret_refresh_key
JWT_ACCESS_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
BCRYPT_ROUNDS=10
MAX_LOGIN_ATTEMPTS=5
LOCKOUT_TIME=900000
PORT=3000Token Cleanup
// Clean up expired tokens (run periodically)
await auth.db.cleanupExpiredTokens(auth.options.tables.refreshTokens);
// With cron job
const cron = require('node-cron');
cron.schedule('0 0 * * *', async () => {
await auth.db.cleanupExpiredTokens(auth.options.tables.refreshTokens);
console.log('Cleaned up expired tokens');
});Direct Database Access
// Get raw database pool for custom queries
const pool = auth.getPool();
const [rows] = await pool.execute(
'SELECT COUNT(*) as total FROM secure_auth_users WHERE isActive = ?',
[true]
);
console.log('Active users:', rows[0].total);๐ง Troubleshooting
Connection Timeout (ETIMEDOUT)
If you're getting ETIMEDOUT errors:
const auth = new SecureNodeAuth({
connection: {
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp',
// Add these timeout settings
connectTimeout: 20000, // 20 seconds (default: 10s)
acquireTimeout: 20000, // 20 seconds (default: 10s)
timeout: 20000, // 20 seconds (default: 10s)
retryAttempts: 5, // Retry 5 times (default: 3)
retryDelay: 2000 // Wait 2s between retries (default: 1s)
}
});Common causes:
- โ
MySQL server not running โ
sudo service mysql start - โ Wrong host/port โ Verify connection details
- โ Firewall blocking connection โ Check firewall rules
- โ
MySQL not accepting remote connections โ Edit
my.cnf(bind-address)
Connection Refused (ECONNREFUSED)
# Check if MySQL is running
sudo service mysql status
# Start MySQL
sudo service mysql start
# Check MySQL port
netstat -an | grep 3306Access Denied (ER_ACCESS_DENIED_ERROR)
-- Grant permissions to user
GRANT ALL PRIVILEGES ON myapp.* TO 'myuser'@'localhost';
FLUSH PRIVILEGES;Slow Initialization
Enable connection pooling (already enabled by default):
const auth = new SecureNodeAuth({
connection: {
connectionLimit: 20, // Max connections (default: 10)
queueLimit: 0, // No queue limit (default: 0)
enableKeepAlive: true, // Keep connections alive (default: true)
keepAliveInitialDelay: 0 // Initial delay (default: 0)
}
});๐ Additional Guides
- ๐๏ธ PostgreSQL Integration Guide - Complete guide for PostgreSQL, migration, and Docker setup
- โก Fastify Integration Guide - Complete guide for using with Fastify framework
- ๐ Accessing User-Specific Data - Complete guide on protecting routes and accessing user's posts, orders, etc.
- โ ๏ธ Dangerous Migrations Guide - Runtime schema changes for existing databases (use with caution)
- ๐ Authentication Flow Diagram - Visual guide showing how authentication works
- โก Quick Reference - Common patterns cheat sheet
- ๐ Getting Started - Step-by-step setup guide
- ๐ Security Documentation - Comprehensive security features and best practices
- ๐ Security Audit Report - Expert-level security audit results (49 issues resolved)
๐ Security Features
This package has undergone 5 rounds of comprehensive security audits and implements industry best practices:
- โ SQL Injection Protection: Parameterized queries + escaped identifiers
- โ Token Hashing: SHA-256 hashing of refresh tokens in database
- โ Email Normalization: Prevents duplicate accounts via case variations
- โ Audit Logging: Configurable logging for all security events
- โ Brute Force Protection: Account lockout after failed attempts
- โ Password Security: Bcrypt with configurable rounds (4-31)
- โ Input Validation: Multi-layer validation and sanitization
- โ Secure Configuration: Validated defaults with safe fallbacks
Security Standards Compliance: OWASP Top 10, NIST Framework, PCI-DSS, GDPR
See SECURITY.md for complete security documentation.
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
๐ License
MIT ยฉ 2025
๐ Links
๐ก Support
If you find this package helpful, please consider:
- โญ Starring the repository
- ๐ Reporting bugs
- ๐ก Suggesting new features
- ๐ Improving documentation
Built with โค๏ธ for the Node.js community