Package Exports
- @ldauth/node
- @ldauth/node/express
- @ldauth/node/fastify
Readme
@ldauth/node
Node.js client library for ldauth permission checking. This library provides a simple way to integrate permission checking into your Node.js applications using the ldauth authentication and authorization service.
Features
- 🔐 Simple permission checking against ldauth API
- ⚡ Built-in caching for improved performance
- 🎯 Framework integrations for Fastify and Express
- 🔍 Optional local JWT validation
- 💪 TypeScript support with full type definitions
- 🛡️ Comprehensive error handling
Installation
npm install @ldauth/node
# or
yarn add @ldauth/node
# or
pnpm add @ldauth/node
Quick Start
Basic Usage
import { LDAuthClient } from '@ldauth/node';
const ldauth = new LDAuthClient({
apiUrl: 'https://auth.example.com',
defaultSchema: 'myapp',
cacheTime: 5 // Cache results for 5 seconds
});
// Check a permission
try {
await ldauth.checkPermission(token, {
resource: 'users',
action: 'read'
});
console.log('Permission granted!');
} catch (error) {
console.error('Permission denied');
}
// Get all user permissions
const permissions = await ldauth.getUserPermissions(token);
console.log(permissions);
// { permissions: { users: ['read', 'write'], posts: ['read'] } }
// Get user info
const userInfo = await ldauth.getUserInfo(token);
console.log(userInfo);
// { id: '123', email: 'user@example.com', groups: ['admin'] }
Fastify Integration
import fastify from 'fastify';
import { ldauthFastify } from '@ldauth/node/fastify';
const app = fastify();
// Register the plugin
await app.register(ldauthFastify, {
apiUrl: 'https://auth.example.com',
defaultSchema: 'myapp',
validateTokenLocally: true, // Validate JWT before calling API
cacheTime: 5
});
// Simple permission check
app.get('/users', {
preHandler: app.ldauth.require('users', 'read')
}, async (request, reply) => {
return { users: [] };
});
// With user info populated
app.get('/profile', {
preHandler: [
app.ldauth.require('profile', 'view'),
app.ldauth.populateUser()
]
}, async (request, reply) => {
return {
email: request.user.email,
groups: request.user.groups
};
});
// Check multiple permissions (AND)
app.post('/admin', {
preHandler: app.ldauth.requireAll([
['admin', 'access'],
['settings', 'write']
])
}, async (request, reply) => {
return { success: true };
});
// Check multiple permissions (OR)
app.put('/content', {
preHandler: app.ldauth.requireAny([
['content', 'edit'],
['admin', 'access']
])
}, async (request, reply) => {
return { success: true };
});
Express Integration
import express from 'express';
import { ldauthExpress } from '@ldauth/node/express';
const app = express();
// Create middleware factory
const ldauth = ldauthExpress({
apiUrl: 'https://auth.example.com',
defaultSchema: 'myapp',
validateTokenLocally: true,
cacheTime: 5
});
// Simple permission check
app.get('/users',
ldauth.require('users', 'read'),
(req, res) => {
res.json({ users: [] });
}
);
// With user info populated
app.get('/profile',
ldauth.require('profile', 'view'),
ldauth.populateUser(),
(req, res) => {
res.json({
email: req.user.email,
groups: req.user.groups
});
}
);
// Check multiple permissions (AND)
app.post('/admin',
ldauth.requireAll([
['admin', 'access'],
['settings', 'write']
]),
(req, res) => {
res.json({ success: true });
}
);
// Check multiple permissions (OR)
app.put('/content',
ldauth.requireAny([
['content', 'edit'],
['admin', 'access']
]),
(req, res) => {
res.json({ success: true });
}
);
// Global middleware for all /api routes
app.use('/api', ldauth.populateUser());
Configuration
Client Options
interface LDAuthClientConfig {
// Base URL of your ldauth API gateway
apiUrl?: string; // Can use LDAUTH_API_URL env var
// Default schema for permission checks
defaultSchema?: string;
// Default profile (defaults to '__default')
defaultProfile?: string;
// Validate JWT locally before API call
validateTokenLocally?: boolean; // Default: false
// Cache results for this many seconds
cacheTime?: number; // Default: 0 (no cache)
// API request timeout in milliseconds
timeout?: number; // Default: 10000
// Custom headers for API requests
headers?: Record<string, string>;
}
Environment Variables
LDAUTH_API_URL
- Set the API URL via environment variable instead of config
Error Handling
The library provides specific error classes for different scenarios:
import {
LDAuthPermissionError,
LDAuthTokenError,
LDAuthAPIError,
LDAuthConfigError
} from '@ldauth/node';
try {
await ldauth.checkPermission(token, {
resource: 'users',
action: 'delete'
});
} catch (error) {
if (error instanceof LDAuthPermissionError) {
// Permission was denied
console.log('Required permission:', error.requiredPermission);
} else if (error instanceof LDAuthTokenError) {
// Token is invalid or expired
console.log('Token error:', error.message);
} else if (error instanceof LDAuthAPIError) {
// API communication failed
console.log('API error:', error.statusCode, error.message);
}
}
Express Error Handler
app.use((err, req, res, next) => {
if (err.name === 'LDAuthPermissionError') {
res.status(403).json({
error: 'Permission denied',
required: err.requiredPermission
});
} else if (err.name === 'LDAuthTokenError') {
res.status(401).json({
error: 'Invalid token'
});
} else {
next(err);
}
});
Advanced Usage
Custom Token Extraction
// Fastify
await app.register(ldauthFastify, {
apiUrl: 'https://auth.example.com',
extractToken: (request) => {
// Get token from custom header or cookie
return request.headers['x-auth-token'] ||
request.cookies?.authToken;
}
});
// Express
const ldauth = ldauthExpress({
apiUrl: 'https://auth.example.com',
extractToken: (req) => {
// Get token from custom header or cookie
return req.headers['x-auth-token'] ||
req.cookies?.authToken;
}
});
Object-Level Permissions
// Check permission for a specific resource instance
await ldauth.checkPermission(token, {
resource: 'posts',
action: 'edit',
instanceId: 'post-123' // Check for this specific post
});
Custom Schema and Profile
// Override default schema and profile
await ldauth.checkPermission(token, {
resource: 'admin',
action: 'access',
schema: 'admin-portal',
profile: 'elevated'
});
API Reference
LDAuthClient
checkPermission(token, options)
Check if the user has a specific permission.
getUserPermissions(token, options?)
Get all permissions for the user.
getUserInfo(token)
Get user information from the token.
getClientIdFromToken(token)
Extract client ID from token without validation.
clearCache()
Clear all cached results.
Framework Integrations
Both Fastify and Express integrations provide:
require(resource, action, options?)
- Require a single permissionrequireAll(permissions)
- Require all specified permissionsrequireAny(permissions)
- Require at least one permissionpopulateUser()
- Add user info to requestpopulatePermissions(options?)
- Add all permissions to request
License
MIT