npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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-database for 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/maauth

Quick 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 login
  • POST /api/v1/auth/password-change - Change password
  • POST /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 info
  • POST /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-token

Request (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-token

Request:

{
  "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-token

GET /api/v1/auth/users

Get all users (admin only).

Headers:

Authorization: Bearer admin-jwt-token

Response:

{
  "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-token

Response:

{
  "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-token

Response:

{
  "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.sqlite
require('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 isRoot flag, 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

  1. Change Default Password: Always change the root password
  2. Custom Root Username: Consider using a custom root username for security
  3. Use Environment Variables: Store JWT secret and root credentials in environment variables
  4. Use HTTPS: Always use HTTPS in production
  5. Token Expiry: Set appropriate token expiry times
  6. Validate Input: Always validate user input on frontend
  7. Handle Errors: Implement proper error handling
  8. Logout Handling: Clear tokens on logout
  9. 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: true flag
  • 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.