@maplex-studio/maauth
v1.2.5
Published
A simple, powerful JWT-based authentication middleware for Express.js with built-in user management and database integration.
Readme
MaAuth
A simple, powerful JWT-based authentication middleware for Express.js with built-in user management and database integration.
Features
- 🔐 JWT Authentication - Secure token-based authentication
- 👤 User Management - Built-in user creation, deletion, and password management
- 🛡️ Role-Based Access - Admin, user, and root roles with proper permissions
- 👑 Root User Management - Special root user with highest privileges
- 💾 Database Integration - Uses
easy-databasefor seamless data storage - 🚀 Zero Configuration - Works out of the box with sensible defaults
- 🔧 Highly Configurable - Customize everything to fit your needs
Installation
npm install @maplex-studio/maauthQuick Start
import express from 'express';
import createAuth from '@maplex-studio/maauth';
const app = express();
// Add authentication middleware
app.use(createAuth());
// Your other routes
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server running on port 3000');
console.log('Login at: http://localhost:3000/api/v1/auth/login');
console.log('Default credentials: root / changeme');
});That's it! Your app now has full authentication with these routes:
POST /api/v1/auth/login- User loginPOST /api/v1/auth/password-change- Change passwordPOST /api/v1/auth/create-user- Create new user (admin only)DELETE /api/v1/auth/delete-user/:username- Delete user (admin only)GET /api/v1/auth/users- List all users (admin only)GET /api/v1/auth/root- Get root user info (root only)GET /api/v1/auth/me- Get current user infoPOST /api/v1/auth/logout- Logout
Configuration
const createAuth = require('@maplex-studio/maauth');
app.use(createAuth({
jwtSecret: 'your-super-secret-key', // JWT signing secret
jwtExpiry: '24h', // Token expiry time
apiPrefix: '/api/v1/auth', // API route prefix
saltRounds: 10, // bcrypt salt rounds
rootUsername: 'superadmin', // Custom root username
rootPassword: 'mysecretpassword', // Custom root password
database: { // Database options
storage: './myauth.sqlite',
logging: false
}
}));API Reference
Authentication Routes
POST /api/v1/auth/login
Login with username and password.
Request:
{
"username": "root",
"password": "changeme"
}Response:
{
"success": true,
"message": "Login successful",
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"id": 1,
"username": "root",
"role": "admin",
"isRoot": true,
"lastLogin": "2024-01-15T10:30:00.000Z"
}
}POST /api/v1/auth/password-change
Change password (requires authentication).
Headers:
Authorization: Bearer your-jwt-tokenRequest (change own password):
{
"currentPassword": "oldpassword",
"newPassword": "newpassword"
}Request (admin changing another user's password):
{
"targetUsername": "someuser",
"newPassword": "newpassword"
}POST /api/v1/auth/create-user
Create a new user (admin only).
Headers:
Authorization: Bearer admin-jwt-tokenRequest:
{
"username": "newuser",
"password": "userpassword",
"role": "user"
}Response:
{
"success": true,
"message": "User created successfully",
"user": {
"id": 2,
"username": "newuser",
"role": "user",
"isActive": true,
"isRoot": false
}
}DELETE /api/v1/auth/delete-user/:username
Delete a user (admin only). Root user cannot be deleted.
Headers:
Authorization: Bearer admin-jwt-tokenGET /api/v1/auth/users
Get all users (admin only).
Headers:
Authorization: Bearer admin-jwt-tokenResponse:
{
"success": true,
"users": [
{
"id": 1,
"username": "root",
"role": "admin",
"isRoot": true,
"createdAt": "2024-01-15T10:00:00.000Z",
"lastLogin": "2024-01-15T10:30:00.000Z"
}
]
}GET /api/v1/auth/root
Get root user information (root only).
Headers:
Authorization: Bearer root-jwt-tokenResponse:
{
"success": true,
"rootUser": {
"id": 1,
"username": "root",
"role": "admin",
"isRoot": true,
"createdAt": "2024-01-15T10:00:00.000Z",
"lastLogin": "2024-01-15T10:30:00.000Z",
"isActive": true
}
}GET /api/v1/auth/me
Get current user information.
Headers:
Authorization: Bearer your-jwt-tokenResponse:
{
"success": true,
"user": {
"id": 1,
"username": "root",
"role": "admin",
"isRoot": true,
"createdAt": "2024-01-15T10:00:00.000Z",
"lastLogin": "2024-01-15T10:30:00.000Z"
}
}Protecting Routes
Protect Individual Routes
const express = require('express');
const createAuth = require('@maplex-studio/maauth');
const app = express();
// Add auth middleware
app.use(createAuth());
// Protected route - requires valid JWT
app.get('/protected', createAuth.protect(), (req, res) => {
res.json({
message: 'This is protected!',
user: req.user // JWT payload available here
});
});
// Admin only route
app.get('/admin-only', createAuth.adminOnly(), (req, res) => {
res.json({
message: 'Admin access granted!',
user: req.user
});
});
// Root only route - highest privilege level
app.get('/root-only', createAuth.rootOnly(), (req, res) => {
res.json({
message: 'Root access granted!',
user: req.user
});
});Protect Route Groups
const router = express.Router();
// All routes in this router require authentication
router.use(createAuth.protect());
router.get('/dashboard', (req, res) => {
res.json({ message: 'Dashboard data', user: req.user });
});
router.get('/profile', (req, res) => {
res.json({ message: 'User profile', user: req.user });
});
app.use('/app', router);Root-Only Route Group
const rootRouter = express.Router();
// All routes in this router require root access
rootRouter.use(createAuth.rootOnly());
rootRouter.get('/system-config', (req, res) => {
res.json({ message: 'System configuration', user: req.user });
});
rootRouter.get('/critical-settings', (req, res) => {
res.json({ message: 'Critical system settings', user: req.user });
});
app.use('/root', rootRouter);User Roles and Permissions
The system supports three levels of access:
1. Regular Users (role: "user")
- Can login and access protected routes
- Can change their own password
- Can view their own profile
2. Admin Users (role: "admin")
- All user permissions
- Can create new users
- Can delete users (except root)
- Can change any user's password
- Can list all users
3. Root User (isRoot: true)
- All admin permissions
- Highest privilege level
- Cannot be deleted
- Has access to root-only routes
- Can access special root user information
Frontend Integration
Login Example (JavaScript)
async function login(username, password) {
const response = await fetch('/api/v1/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password })
});
const data = await response.json();
if (data.success) {
// Store token
localStorage.setItem('authToken', data.token);
console.log('Logged in as:', data.user.username);
console.log('Is root:', data.user.isRoot);
console.log('Role:', data.user.role);
} else {
console.error('Login failed:', data.message);
}
}Making Authenticated Requests
async function makeAuthenticatedRequest(url) {
const token = localStorage.getItem('authToken');
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
return response.json();
}
// Usage
const userInfo = await makeAuthenticatedRequest('/api/v1/auth/me');
const protectedData = await makeAuthenticatedRequest('/protected');
// Root-only request
const rootInfo = await makeAuthenticatedRequest('/api/v1/auth/root');React Hook Example
import { useState, useEffect } from 'react';
function useAuth() {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const token = localStorage.getItem('authToken');
if (token) {
fetch('/api/v1/auth/me', {
headers: { 'Authorization': `Bearer ${token}` }
})
.then(res => res.json())
.then(data => {
if (data.success) {
setUser(data.user);
}
setLoading(false);
});
} else {
setLoading(false);
}
}, []);
const login = async (username, password) => {
const response = await fetch('/api/v1/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
});
const data = await response.json();
if (data.success) {
localStorage.setItem('authToken', data.token);
setUser(data.user);
}
return data;
};
const logout = () => {
localStorage.removeItem('authToken');
setUser(null);
};
return {
user,
loading,
login,
logout,
isRoot: user?.isRoot || false,
isAdmin: user?.role === 'admin' || false
};
}Advanced Usage
Custom Root User Configuration
app.use(createAuth({
rootUsername: 'superadmin', // Custom root username
rootPassword: 'ultra-secure-password', // Custom root password
jwtSecret: process.env.JWT_SECRET,
jwtExpiry: '7d'
}));Custom Database Configuration
app.use(createAuth({
database: {
dialect: 'postgres',
host: 'localhost',
port: 5432,
username: 'dbuser',
password: 'dbpass',
database: 'myapp'
}
}));Environment Variables
# .env file
JWT_SECRET=your-super-secret-jwt-key
JWT_EXPIRY=24h
ROOT_USERNAME=superadmin
ROOT_PASSWORD=ultra-secure-password
DB_PATH=./production.sqliterequire('dotenv').config();
app.use(createAuth({
jwtSecret: process.env.JWT_SECRET,
jwtExpiry: process.env.JWT_EXPIRY,
rootUsername: process.env.ROOT_USERNAME,
rootPassword: process.env.ROOT_PASSWORD,
database: {
storage: process.env.DB_PATH
}
}));Error Handling
The middleware provides consistent error responses:
{
"success": false,
"message": "Error description"
}Common HTTP status codes:
400- Bad Request (missing fields)401- Unauthorized (invalid credentials)403- Forbidden (insufficient permissions)404- Not Found (user doesn't exist)409- Conflict (username already exists)500- Internal Server Error
Security Features
- Password Hashing - Uses bcrypt with configurable salt rounds
- JWT Tokens - Secure, stateless authentication with user ID tracking
- Role-Based Access - Admin, user, and root roles
- Root User Protection - Root user identified by
isRootflag, not username - Input Validation - Validates all user inputs
- Protected Root User - Root user cannot be deleted by any user
- Active User Check - Only active users can login
- Flexible Root Identity - Root user can have any username
Default Users
When first started, the system creates:
- Username:
root(configurable) - Password:
changeme(configurable) - Role:
admin - isRoot:
true
⚠️ Important: Change the root password immediately in production!
Best Practices
- Change Default Password: Always change the root password
- Custom Root Username: Consider using a custom root username for security
- Use Environment Variables: Store JWT secret and root credentials in environment variables
- Use HTTPS: Always use HTTPS in production
- Token Expiry: Set appropriate token expiry times
- Validate Input: Always validate user input on frontend
- Handle Errors: Implement proper error handling
- Logout Handling: Clear tokens on logout
- Root Access: Use root-only routes sparingly for critical operations
Complete Example
const express = require('express');
const createAuth = require('@maplex-studio/maauth');
const app = express();
// Configure authentication
app.use(createAuth({
jwtSecret: process.env.JWT_SECRET || 'dev-secret-change-this',
jwtExpiry: '24h',
rootUsername: process.env.ROOT_USERNAME || 'superadmin',
rootPassword: process.env.ROOT_PASSWORD || 'changeme',
database: { storage: './myapp.sqlite' }
}));
// Public routes
app.get('/', (req, res) => {
res.send('Welcome! Login at /api/v1/auth/login');
});
// Protected routes
app.get('/dashboard', createAuth.protect(), (req, res) => {
res.json({
message: `Welcome to dashboard, ${req.user.username}!`,
user: req.user,
isRoot: req.user.isRoot
});
});
// Admin only routes
app.get('/admin', createAuth.adminOnly(), (req, res) => {
res.json({
message: 'Admin panel access granted',
user: req.user
});
});
// Root only routes
app.get('/system', createAuth.rootOnly(), (req, res) => {
res.json({
message: 'System administration access granted',
user: req.user,
rootAccess: true
});
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
console.log(`👤 Default root user will be created on first run`);
console.log(`🔑 Username: ${process.env.ROOT_USERNAME || 'root'}`);
console.log(`🔑 Password: ${process.env.ROOT_PASSWORD || 'changeme'}`);
});Migration Guide
If you're upgrading from an earlier version:
User IDs
- All users now have unique integer IDs
- JWT tokens include user IDs for better tracking
Root User Changes
- Root user is now identified by
isRoot: trueflag - Root username is configurable
- Root user cannot be deleted regardless of username
New Routes
GET /api/v1/auth/root- Get root user information (root only)
New Middleware
createAuth.rootOnly()- Protect routes for root user only
License
MIT License - see LICENSE file for details.
