@maplex-lib/auth
v2.0.1
Published
Maplex Auth
Downloads
19
Readme
Maplex Auth
A comprehensive authentication middleware for Express.js applications with JWT token management, user roles, and database integration.
✨ Features
- 🔐 JWT Authentication - Secure token-based authentication
- 👥 Role-Based Access Control - Support for user and admin roles
- 🛡️ Root User Management - Special root user with elevated privileges
- 🔑 Password Management - Secure password hashing and change functionality
- 📊 User Management - Complete CRUD operations for users
- 🗄️ Database Integration - Works with @maplex-lib/database
- 🚀 Easy Setup - Simple configuration and initialization
- 🔒 Middleware Protection - Protect routes with authentication requirements
📦 Installation
npm install @maplex-lib/auth @maplex-lib/database🚀 Quick Start
import express from 'express';
import { Database } from '@maplex-lib/database';
import createAuth from '@maplex-lib/auth';
async function main() {
const app = express();
// Initialize and connect database first
const db = new Database(); // Uses in-memory SQLite by default
await db.connect(); // This is the key step you might be missing
// Now create auth with connected database
const auth = createAuth({
database: db,
jwtSecret: 'your-secret-key',
rootUsername: 'admin',
rootPassword: 'secure-password'
});
app.use(auth);
// Protected route example
app.get('/protected', createAuth.protect({ database: db }), (req, res) => {
res.json({ message: 'This is a protected route!' });
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
}
main().catch(console.error);With Persistent Storage
import express from 'express';
import { Database } from '@maplex-lib/database';
import createAuth from '@maplex-lib/auth';
import fs from 'fs';
import path from 'path';
async function main() {
const app = express();
// Ensure data directory exists for persistent storage
const dataDir = './data';
if (!fs.existsSync(dataDir)) {
fs.mkdirSync(dataDir, { recursive: true });
}
// Initialize database with file storage
const db = new Database({
storage: path.join(dataDir, 'app.db')
});
await db.connect();
// Initialize auth middleware
const auth = createAuth({
database: db,
jwtSecret: 'your-secret-key',
rootUsername: 'admin',
rootPassword: 'secure-password'
});
app.use(auth);
app.listen(3000, () => {
console.log('Server running on port 3000');
});
}
main().catch(console.error);⚙️ Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| database | Database | Required | Database instance from @maplex-lib/database |
| jwtSecret | string | 'your-super-secret-jwt-key-change-this' | Secret key for JWT signing |
| jwtExpiry | number \| string | '24h' | Token expiration time |
| apiPrefix | string | '/api/v1/auth' | API endpoint prefix |
| saltRounds | number | 10 | bcrypt salt rounds for password hashing |
| rootUsername | string | 'root' | Default root user username |
| rootPassword | string | 'changeme' | Default root user password |
🛣️ API Endpoints
All endpoints are prefixed with /api/v1/auth by default.
Authentication
POST /login
Authenticate user and receive JWT token.
Request Body:
{
"username": "string",
"password": "string"
}Response:
{
"success": true,
"message": "Login successful",
"token": "jwt-token-here",
"user": {
"id": 1,
"username": "john_doe",
"role": "user",
"isRoot": false,
"isActive": true
}
}POST /logout
Logout user (client-side token removal).
User Management
GET /me
Get current user information (requires authentication).
POST /password-change
Change password (requires authentication).
Request Body:
{
"currentPassword": "string",
"newPassword": "string",
"targetUsername": "string" // Optional, admin only
}POST /create-user (Admin Only)
Create a new user.
Request Body:
{
"username": "string",
"password": "string",
"role": "user" // or "admin"
}GET /users (Admin Only)
Get list of all users.
DELETE /delete-user/:username (Admin Only)
Delete a user by username.
GET /root (Root Only)
Get root user information.
🛡️ Middleware Protection
Basic Protection
app.get('/protected-route', createAuth.protect({ database: db }), (req, res) => {
// Only authenticated users can access
console.log('User:', req.user);
res.json({ message: 'Protected content' });
});Admin Only Protection
app.get('/admin-only', createAuth.adminOnly({ database: db }), (req, res) => {
// Only admin users can access
res.json({ message: 'Admin content' });
});Root Only Protection
app.get('/root-only', createAuth.rootOnly({ database: db }), (req, res) => {
// Only root user can access
res.json({ message: 'Root content' });
});📊 User Roles
The system supports three levels of access:
| Role | Description | Permissions | |------|-------------|-------------| | User | Standard user | Basic authenticated access | | Admin | Administrator | User management, all user permissions | | Root | Super administrator | All permissions, cannot be deleted |
🔧 Advanced Usage
Custom Authentication Check
import { AuthRequest } from '@maplex-lib/auth';
app.get('/custom-protected', createAuth.protect({ database: db }), (req: AuthRequest, res) => {
const user = req.user; // Contains: id, username, role, isRoot
if (user?.role === 'admin') {
res.json({ message: 'Welcome admin!' });
} else {
res.json({ message: 'Welcome user!' });
}
});Multiple Auth Instances
const publicAuth = createAuth({
database: publicDb,
apiPrefix: '/api/public/auth'
});
const adminAuth = createAuth({
database: adminDb,
apiPrefix: '/api/admin/auth'
});
app.use(publicAuth);
app.use(adminAuth);📝 TypeScript Support
Full TypeScript support with comprehensive type definitions:
import createAuth, { AuthRequest, UserPayload, AuthOptions } from '@maplex-lib/auth';
interface CustomRequest extends AuthRequest {
customProperty?: string;
}
app.get('/typed-route', createAuth.protect({ database: db }), (req: CustomRequest, res) => {
const user: UserPayload = req.user!;
// Full type safety
});🔒 Security Features
- Password Hashing: Uses bcrypt with configurable salt rounds
- JWT Tokens: Secure token-based authentication
- Role-Based Access: Granular permission control
- Input Validation: Validates all user inputs
- Error Handling: Secure error messages without information leakage
- Active User Check: Only active users can authenticate
🚨 Important Security Notes
- Change Default Credentials: Always change the default root username and password in production
- Use Strong JWT Secret: Use a cryptographically secure random string for JWT secret
- HTTPS Only: Always use HTTPS in production environments
- Token Storage: Store JWT tokens securely on the client side
- Regular Updates: Keep dependencies updated for security patches
📚 Examples
Check out the /examples directory for complete implementation examples:
- Basic setup
- Role-based routing
- Custom middleware
- Frontend integration
🛠️ Troubleshooting
Common Issues
Database Directory Error
If you encounter ENOENT: no such file or directory, mkdir error:
import fs from 'fs';
import path from 'path';
// Solution 1: Create directory before initializing database
const dataDir = './data';
if (!fs.existsSync(dataDir)) {
fs.mkdirSync(dataDir, { recursive: true });
}
const db = new Database({
storage: path.join(dataDir, 'app.db')
});
// Solution 2: Use in-memory database for testing
const db = new Database({
storage: ':memory:'
});
// Solution 3: Use absolute path
const db = new Database({
storage: path.resolve('./data/app.db')
});Multiple Auth Instances
When using multiple auth instances, ensure each has a unique database instance:
// ❌ Wrong - sharing database instance
const sharedDb = new Database();
const auth1 = createAuth({ database: sharedDb });
const auth2 = createAuth({ database: sharedDb }); // This can cause conflicts
// ✅ Correct - separate database instances
const db1 = new Database({ storage: './data/auth1.db' });
const db2 = new Database({ storage: './data/auth2.db' });
const auth1 = createAuth({ database: db1 });
const auth2 = createAuth({ database: db2 });Contributions are welcome! Please read our contributing guidelines before submitting PRs.
📄 License
MIT License - see LICENSE file for details.
