@starklabs/backend-core
v1.3.6
Published
A comprehensive backend authentication library featuring MongoDB integration, JWT-based authentication, encryption/decryption using libsodium, and utilities for error handling and logging. Supports both ES modules and CommonJS. Requires MONGODB_URI, DB_NA
Downloads
5,705
Readme
@starklabs/backend-core
A comprehensive backend authentication library featuring MongoDB integration, JWT-based authentication, encryption/decryption using libsodium, and utilities for error handling and logging. Supports both ES modules and CommonJS.
Features
- MongoDB Integration: Seamless MongoDB connection management with Mongoose
- JWT Authentication: Sign and verify JWT tokens with configurable expiry
- Encryption/Decryption: Secure data encryption using libsodium (libsodium-wrappers-sumo)
- Error Handling: Custom AppError class for consistent error management
- Structured Logging: AppLog utility for emoji-tagged console logging
- Async Handler: Express middleware wrapper for async route handlers
- Dual Module Support: Works with both ES modules and CommonJS
Installation
npm install @starklabs/backend-coreEnvironment Variables
The following environment variables are required:
MONGODB_URI=mongodb://localhost:27017
DB_NAME=your_database_name
MASTER_KEY=your_base64_encoded_32_byte_key
JWT_SECRET=your_jwt_secret_string
JWT_EXPIRY=1dGenerating MASTER_KEY and JWT_SECRET
Generate both keys using the crypto utilities:
import { crypto } from '@starklabs/backend-core';
// Generate 32-byte master key for encryption
const masterKey = await crypto.generateMasterKey();
console.log(masterKey); // Use this in .env as MASTER_KEY
// Generate 64-byte JWT secret for token signing
const jwtSecret = await crypto.generateJWTSecret();
console.log(jwtSecret); // Use this in .env as JWT_SECRETStore the generated values in your .env file:
MASTER_KEY=eZkZDoy2s+DvGe44QGa7AdU41nKhglEaIjFsxfQCKao=
JWT_SECRET=your_generated_jwt_secret_base64_stringUsage
ES Modules
import starkAuth, { crypto, AppError, AppLog, asyncHandler } from '@starklabs/backend-core';
// Initialize
const auth = await starkAuth.create({
MONGODB_URI: process.env.MONGODB_URI,
DB_NAME: process.env.DB_NAME,
MASTER_KEY: process.env.MASTER_KEY,
JWT_SECRET: process.env.JWT_SECRET,
JWT_EXPIRY: process.env.JWT_EXPIRY || '1d'
});
// Sign JWT
const token = auth.signJWT({ userId: '123', email: '[email protected]' });
// Verify JWT
const payload = auth.verifyJWT(token);
console.log(payload); // { userId: '123', email: '[email protected]', iat: ..., exp: ... }
// Encrypt data
const encrypted = await auth.encrypt('sensitive data');
// Returns: { str, nonce, publicKey, securedPrivateKey }
// Decrypt data
const decrypted = await auth.decrypt(
encrypted.str,
encrypted.nonce,
encrypted.publicKey,
encrypted.securedPrivateKey
);
console.log(decrypted); // 'sensitive data'CommonJS
const starkAuth = require('@starklabs/backend-core');
// Initialize
const auth = await starkAuth.create({
MONGODB_URI: process.env.MONGODB_URI,
DB_NAME: process.env.DB_NAME,
MASTER_KEY: process.env.MASTER_KEY,
JWT_SECRET: process.env.JWT_SECRET,
JWT_EXPIRY: process.env.JWT_EXPIRY || '1d'
});
// Same API as ES modules
const token = auth.signJWT({ userId: '123' });
const payload = auth.verifyJWT(token);API Documentation
StarkAuth Class
static async create(config)
Initializes database connection and returns a new StarkAuth instance.
Parameters:
config.MONGODB_URI(string): MongoDB connection URIconfig.DB_NAME(string): Database nameconfig.MASTER_KEY(string): Base64-encoded 32-byte encryption keyconfig.JWT_SECRET(string): Secret for JWT signingconfig.JWT_EXPIRY(string): JWT expiry time (e.g., "1d", "24h", "7d")
Returns: Promise<StarkAuth>
const auth = await starkAuth.create({
MONGODB_URI: 'mongodb://localhost:27017',
DB_NAME: 'myapp',
MASTER_KEY: 'eZkZDoy2s+DvGe44QGa7AdU41nKhglEaIjFsxfQCKao=',
JWT_SECRET: 'your-secret-key',
JWT_EXPIRY: '7d'
});async encrypt(str)
Encrypts a string using the master key.
Parameters:
str(string): String to encrypt
Returns: Promise<{ str, nonce, publicKey, securedPrivateKey }>
const encrypted = await auth.encrypt('credit card number');
// Store all fields: str, nonce, publicKey, securedPrivateKeyasync decrypt(str, nonce, publicKey, securedPrivateKey)
Decrypts an encrypted string.
Parameters:
str(string): Encrypted data (base64)nonce(string): Nonce (base64)publicKey(string): Public key (base64)securedPrivateKey(string): Secured private key (base64)
Returns: Promise<string>
const original = await auth.decrypt(
encrypted.str,
encrypted.nonce,
encrypted.publicKey,
encrypted.securedPrivateKey
);signJWT(payload)
Signs a JWT token.
Parameters:
payload(object): Data to encode in token
Returns: string (JWT token)
Supported Expiry Values:
"2m","10m","1h","6h","12h","1d","3d","7d","14d","30d"
const token = auth.signJWT({
userId: '507f1f77bcf86cd799439011',
role: 'admin',
email: '[email protected]'
});verifyJWT(token)
Verifies and decodes a JWT token.
Parameters:
token(string): JWT token to verify
Returns: object (decoded payload)
Throws: AppError if token is invalid or expired
try {
const payload = auth.verifyJWT(token);
console.log(payload.userId);
} catch (error) {
console.error('Invalid token:', error.message);
}Crypto Utilities
crypto.generateMasterKey()
Generates a secure 32-byte master key encoded in base64.
Returns: Promise<string>
const key = await crypto.generateMasterKey();
console.log(key); // "eZkZDoy2s+DvGe44QGa7AdU41nKhglEaIjFsxfQCKao="crypto.generateJWTSecret()
Generates a secure 64-byte JWT secret encoded in base64.
Returns: Promise<string>
const secret = await crypto.generateJWTSecret();
console.log(secret); // "long_base64_encoded_string_suitable_for_jwt_signing"crypto.hash(password)
Hashes a password using argon2i algorithm.
Parameters:
password(string): Password to hash
Returns: Promise<string> (salt + hash in base64)
const hashedPassword = await crypto.hash('myPassword123');
// Store hashedPassword in databasecrypto.verifyHash(password, storedHash)
Verifies a password against a stored hash.
Parameters:
password(string): Password to verifystoredHash(string): Hash from database
Returns: Promise<boolean>
const isValid = await crypto.verifyHash('myPassword123', storedHash);
if (isValid) {
console.log('Password correct');
} else {
console.log('Password incorrect');
}Utility Exports
AppError
Custom error class for application errors.
import { AppError } from '@starklabs/backend-core';
throw new AppError('User not found', 404);Constructor: new AppError(message, statusCode)
AppLog
Structured logging utility with emoji tags.
import { AppLog } from '@starklabs/backend-core';
AppLog('check', 'auth.js', 'User authenticated successfully');
// Output: ✅ [auth.js] User authenticated successfully
AppLog('X', 'auth.js', 'Authentication failed');
// Output: ❌ [auth.js] Authentication failedParameters: AppLog(emoji, file, message)
emoji(string):'check'or'X'file(string): File name for contextmessage(string): Log message
asyncHandler
Express middleware wrapper for handling async errors.
import { asyncHandler } from '@starklabs/backend-core';
import express from 'express';
const app = express();
app.post('/login', asyncHandler(async (req, res, next) => {
// Any thrown errors will be passed to next(error)
const user = await findUser(req.body.email);
res.json({ user });
}));Complete Example
Express Server with Authentication
import express from 'express';
import starkAuth, { asyncHandler, AppLog, AppError } from '@starklabs/backend-core';
const app = express();
app.use(express.json());
let auth;
// Initialize auth middleware
app.use(async (req, res, next) => {
if (!auth) {
auth = await starkAuth.create({
MONGODB_URI: process.env.MONGODB_URI,
DB_NAME: process.env.DB_NAME,
MASTER_KEY: process.env.MASTER_KEY,
JWT_SECRET: process.env.JWT_SECRET,
JWT_EXPIRY: '7d'
});
}
req.auth = auth;
next();
});
// Login endpoint
app.post('/login', asyncHandler(async (req, res) => {
const { email, password } = req.body;
if (!email || !password) {
throw new AppError('Email and password required', 400);
}
// Verify credentials (pseudo code)
const user = { id: '123', email };
const token = req.auth.signJWT({
userId: user.id,
email: user.email
});
AppLog('check', 'login', `User ${email} logged in`);
res.json({ token });
}));
// Protected endpoint with JWT verification
app.get('/profile', asyncHandler(async (req, res) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
throw new AppError('Token required', 401);
}
const payload = req.auth.verifyJWT(token);
res.json({ userId: payload.userId, email: payload.email });
}));
// Error handler
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
const message = err.message || 'Internal Server Error';
AppLog('X', 'server', message);
res.status(statusCode).json({ error: message });
});
app.listen(3000, () => {
AppLog('check', 'server', 'Server running on port 3000');
});Error Handling
All methods throw AppError on failure:
import { AppError } from '@starklabs/backend-core';
try {
const payload = auth.verifyJWT(invalidToken);
} catch (error) {
if (error instanceof AppError) {
console.log(error.message); // "Invalid or expired token"
console.log(error.statusCode); // 401
}
}Testing
Run the test suite:
npm testTests verify:
- Instance creation and method existence
- JWT signing/verification
- Encryption/decryption
- Cross-module compatibility (ES ↔ CJS)
- Error handling
Supported Environments
- Node.js: v14+
- Module Systems: ES Modules (
.mjs,"type": "module") and CommonJS (.cjs,.jswith"type": "commonjs") - Databases: MongoDB 4.0+
Dependencies
mongoose: ^9.6.1 - MongoDB ODMjsonwebtoken: ^9.0.3 - JWT signing/verificationlibsodium-wrappers-sumo: ^0.8.4 - Encryption/hashingdotenv: ^17.4.2 - Environment variable managementexpress: ^5.2.1 - Web framework (optional)cors: ^2.8.6 - CORS middleware (optional)helmet: ^8.1.0 - Security headers (optional)
Security Considerations
- MASTER_KEY: Generate a strong key using
crypto.generateMasterKey()and store securely in.env - JWT_SECRET: Generate using
crypto.generateJWTSecret()- this must be kept confidential and should never be shared or committed to version control - Database: Ensure MongoDB is protected with authentication and firewall rules
- HTTPS: Always use HTTPS in production
- Token Storage: Store JWT tokens securely (httpOnly cookies recommended, not localStorage)
- Key Rotation: Consider rotating MASTER_KEY and JWT_SECRET periodically for enhanced security
Common Issues
"Invalid expiry key"
Ensure JWT_EXPIRY is one of the supported values: "2m", "10m", "1h", "6h", "12h", "1d", "3d", "7d", "14d", "30d"
"Error while connecting!"
Check that:
- MongoDB is running and accessible
MONGODB_URIis correct- Network/firewall allows connection
"Invalid or expired token"
- Token may have expired (check
JWT_EXPIRY) JWT_SECRETmay have changed- Token may be malformed or tampered
License
ISC
Author
Musa (@starklabs)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
