@empowerx/exguard-api
v1.2.0
Published
ExGuard Backend Authorization Package - Auto-configurable JWT-based access control with comprehensive decorators and user permission data access for Node.js APIs
Maintainers
Readme
ExGuard RBAC Backend - EmpowerX
🛡️ Auto-configurable JWT-based access control for Node.js APIs with simplified permission management.
🚀 Features
- ✅ Simplified Setup - Only requires
EXGUARD_API_URLto get started - ✅ Auto-Configuration - Generates framework-specific files automatically
- ✅ Optional JWT Verification - Skip JWT verification and rely on your ExGuard API
- ✅ Role-Based Access Control (RBAC) - Check user permissions and roles
- ✅ Framework Agnostic - Works with Express, NestJS, Fastify, and more
- ✅ Built-in Caching - Reduce API calls with configurable TTL cache
- ✅ Module-Based Permissions - Organize permissions by functional modules
- ✅ Field Office Support - Handle regional/office-based access control
- ✅ TypeScript Support - Full type definitions included
📦 Installation
# Install with pnpm (recommended)
pnpm add @empowerx/exguard-api
# Install with npm
npm install @empowerx/exguard-api
# Install with yarn
yarn add @empowerx/exguard-api🚀 Quick Setup (Auto-Configuration)
Method 1: Automatic Setup (Recommended)
The package includes an automatic setup script that runs during installation:
# Install package (auto-setup runs automatically)
pnpm add @empowerx/exguard-apiWhat happens automatically:
- ✅ Detects your framework (NestJS, Express, etc.)
- ✅ Creates
.env.examplewith required environment variables - ✅ Generates framework-specific configuration files
- ✅ Adds
exguard:setupscript to yourpackage.json - ✅ Configures
app.module.tsfor NestJS projects
Method 2: Manual Setup (If auto-setup doesn't run)
If the automatic setup doesn't execute, run it manually:
# First time setup (adds exguard:setup script to package.json)
node node_modules/@empowerx/exguard-api/scripts/setup.js
# Or use the convenient script after first setup
pnpm exguard:setupMethod 3: Alternative Package Managers
# For npm
npm install @empowerx/exguard-api
npm run exguard:setup
# For yarn
yarn add @empowerx/exguard-api
yarn exguard:setup📋 Environment Configuration
Create a .env file from the generated .env.example:
# Required
EXGUARD_API_URL=http://localhost:3001
# JWT Configuration (Optional - for local verification)
# JWT_SECRET=your-jwt-secret-here
# JWKS_URI=https://cognito-idp.region.amazonaws.com/your-user-pool/.well-known/jwks.json
# JWT_ISSUER=https://cognito-idp.region.amazonaws.com/your-user-pool
# JWT_AUDIENCE=your-client-id🛠️ Framework Implementation
NestJS Implementation ⭐ Recommended
After running the setup script, you'll have generated files in src/exguard/:
1. Import ExGuard Module
// src/app.module.ts
import { Module } from '@nestjs/common';
import { ExGuardModule } from './exguard';
@Module({
imports: [
ExGuardModule.forRoot({
exguardApiUrl: process.env.EXGUARD_API_URL,
skipJwtVerification: true,
cacheEnabled: true,
cacheTtl: 300,
}),
// ... other modules
],
})
export class AppModule {}2. Use Guards in Controllers
// src/roles/roles.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { ExGuardGuard, PermissionsGuard, RequirePermissions } from '../exguard';
@Controller('roles')
@UseGuards(ExGuardGuard, PermissionsGuard)
export class RolesController {
@Get()
@RequirePermissions({ module: 'exGUARD', action: 'roles:view_role_list' })
async findAll() {
// Your controller logic
return { roles: [] };
}
@Get(':id')
@RequirePermissions({ module: 'exGUARD', action: 'roles:view_role_details' })
async findOne(@Param('id') id: string) {
// Your controller logic
return { role: null };
}
}3. Access User Information
// In any controller method
@Get('profile')
async getProfile(@Request() req) {
// User info is automatically attached by ExGuardGuard
return {
user: req.user,
permissions: req.user.modules,
roles: req.user.roles,
fieldOffices: req.user.fieldOffices,
};
}Express.js Implementation
After running the setup script, you'll have generated middleware in src/middleware/:
1. Use Middleware in Your App
// src/app.js
const express = require('express');
const { exGuardMiddleware, requirePermission } = require('./middleware/exguard.middleware');
const app = express();
// Apply ExGuard authentication middleware
app.use('/api', exGuardMiddleware());
// Your routes with permission checks
app.get('/api/roles', requirePermission('exGUARD', 'roles:view_role_list'), (req, res) => {
res.json({ roles: [] });
});
app.get('/api/users', requirePermission('exGUARD', 'users:view_user_list'), (req, res) => {
res.json({ users: [] });
});2. Access User Information
// User info is attached to request by exGuardMiddleware
app.get('/api/profile', (req, res) => {
res.json({
user: req.user,
permissions: req.user.modules,
roles: req.user.roles,
});
});🔐 API Reference
ExGuardService
Constructor
new ExGuardService(config: ExGuardConfig)Configuration Options:
// exguard.config.js
module.exports = {
// API Configuration - REQUIRED
exguardApiUrl: process.env.EXGUARD_API_URL || 'http://localhost:3001',
// Optional JWT Configuration
jwtSecret: process.env.JWT_SECRET,
jwksUri: process.env.JWKS_URI,
issuer: process.env.JWT_ISSUER,
audience: process.env.JWT_AUDIENCE,
// Cache Configuration
cacheEnabled: true,
cacheTtl: 300, // 5 minutes
// Skip JWT verification (recommended for simplified setup)
skipJwtVerification: true,
};Core Methods
getUserAccess(accessToken: string): Promise<UserAccess | null>
Get complete user access data including roles, permissions, and groups.
const userAccess = await exGuard.getUserAccess(access_token);
if (userAccess) {
console.log('User:', userAccess.user);
console.log('Roles:', userAccess.roles);
console.log('Groups:', userAccess.groups);
console.log('Modules:', userAccess.modules);
console.log('Field Offices:', userAccess.fieldOffices);
}hasPermission(accessToken: string, permission: PermissionCheck): Promise<boolean>
Check if user has a specific permission.
const canViewRoles = await exGuard.hasPermission(access_token, {
module: 'exGUARD',
action: 'roles:view_role_list'
});
if (canViewRoles) {
// Allow access
} else {
// Deny access
}isInRole(accessToken: string, role: string): Promise<boolean>
Check if user has a specific role.
const isAdmin = await exGuard.isInRole(access_token, 'Administrator');isInGroup(accessToken: string, group: string): Promise<boolean>
Check if user belongs to a specific group.
const isInManagement = await exGuard.isInGroup(access_token, 'Management');getFieldOffices(accessToken: string): Promise<string[]>
Get user's assigned field offices.
const fieldOffices = await exGuard.getFieldOffices(access_token);
console.log('User can access offices:', fieldOffices);📊 Data Models
UserAccess
interface UserAccess {
user: {
id: string;
cognitoSubId: string;
username: string | null;
email: string | null;
emailVerified: boolean;
givenName: string | null;
familyName: string | null;
employeeNumber: string | null;
regionId: string | null;
createdAt: string;
updatedAt: string;
lastLoginAt: string;
fieldOffice?: FieldOffice | null;
};
groups: string[];
roles: string[];
modules: ModulePermission[];
fieldOffices: string[];
}ModulePermission
interface ModulePermission {
key: string;
name: string;
permissions: string[];
}PermissionCheck
interface PermissionCheck {
module: string;
action: string;
}🔄 Caching
The package includes built-in caching to reduce API calls:
const exGuard = new ExGuardService({
exguardApiUrl: 'https://your-exguard-api.com',
cacheEnabled: true,
cacheTtl: 300 // Cache for 5 minutes
});
// First call - hits API
const userAccess1 = await exGuard.getUserAccess(token);
// Second call within 5 minutes - uses cache
const userAccess2 = await exGuard.getUserAccess(token);🚨 Error Handling
const exGuard = new ExGuardService({
exguardApiUrl: 'https://your-exguard-api.com',
onUnauthorized: (error) => {
console.error('Access denied:', error.message);
// Redirect to login or handle error
}
});
try {
const userAccess = await exGuard.getUserAccess(token);
if (!userAccess) {
// Handle unauthorized access
}
} catch (error) {
console.error('ExGuard error:', error);
}📝 File Structure After Auto-Setup
NestJS Project
src/
├── exguard/
│ ├── index.ts # Main exports
│ ├── exguard.config.ts # Configuration
│ ├── exguard.module.ts # NestJS module
│ ├── exguard.guard.ts # Authentication guard
│ ├── permissions.guard.ts # Permission checking guard
│ └── permission.decorator.ts # Permission decorator
├── app.module.ts # Import ExGuardModule here
└── your.controllers.ts # Use guards and decoratorsExpress Project
src/
├── middleware/
│ └── exguard.middleware.js # Express middleware
├── app.js # Use middleware here
└── routes/ # Apply permission checks🎯 Best Practices
- Use Auto-Setup - Run
pnpm exguard:setupfor automatic configuration - Environment Variables - Keep sensitive data in
.envfiles - Permission Naming - Use consistent naming:
module:actionformat - Error Handling - Implement proper error responses for unauthorized access
- Caching - Enable caching for better performance
- Field Office Access - Use field office permissions for regional access control
📝 License
MIT License - see LICENSE file for details.
🤝 Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
📞 Support
For issues and questions:
- Create an issue on GitHub
- Check the troubleshooting section
- Review the API documentation
🚀 Get started in seconds with pnpm exguard:setup!
