JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 108
  • Score
    100M100P100Q86597F
  • License MIT

Node.js client library for ldauth permission checking

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 permission
  • requireAll(permissions) - Require all specified permissions
  • requireAny(permissions) - Require at least one permission
  • populateUser() - Add user info to request
  • populatePermissions(options?) - Add all permissions to request

License

MIT