license-authpkg
v1.5.0
Published
Client library for license key validation and activation
Downloads
21
Maintainers
Readme
License Client
A robust, production-ready license key validation and activation client library for Node.js applications. This package provides everything you need to integrate license key management into your projects.
Features
- ✅ Online & Offline Validation - Works even when disconnected from the internet
- 🔒 Hardware Fingerprinting - Bind licenses to specific devices
- 🔄 Automatic Heartbeat - Periodic license verification in the background
- 🎯 Feature Flags - Control which features are enabled per license tier
- ⏰ Grace Period - Configurable offline validation period
- 📊 Event System - React to license events in your application
- 🛡️ Security - Cryptographic token verification and validation
- 💾 Persistent Storage - Secure local storage of activation data
- 🎨 TypeScript Support - Fully typed for excellent IDE support
- ⚡ WebSocket Real-Time - Instant license revocation and updates
- 📈 Telemetry & Analytics - Built-in usage tracking and monitoring
- 🔒 Force Shutdown - Remote application termination capability
Installation
npm install @yourorg/license-clientCLI Tool
After installation, you can use the CLI tool to help with setup:
# Encrypt your product ID
npx license-client encrypt my-product-id
# Create a config file template
npx license-client init
# Show help
npx license-client helpQuick Start
Note: This package uses encrypted configuration. The API URL is built-in and encrypted.
Two Product ID Modes:
- Pre-assigned: Generate encrypted product IDs using
createEncryptedProductId() - Server-assigned: Let your license server assign product IDs dynamically through your web panel
See USAGE.md for detailed setup instructions.
import { LicenseClient, createEncryptedProductId } from '@yourorg/license-client';
// First, generate your encrypted product ID (do this once):
// const encrypted = createEncryptedProductId('your-product-id');
// console.log(encrypted);
// Use the encrypted product ID in your code
const ENCRYPTED_PRODUCT_ID = 'U2FsdGVkX1+xxxxx...'; // From above step
// Create a license.config.json file with your license key:
// {
// "licenseKey": "XXXX-XXXX-XXXX-XXXX"
// }
// Initialize the client (license key loaded from config file)
const license = new LicenseClient({
encryptedProductId: ENCRYPTED_PRODUCT_ID
});
// Activate the license (if not already activated)
if (!license.isActivated()) {
const result = await license.activate();
if (result.success) {
console.log('License activated!');
}
}
// Validate the license
const validation = await license.validate();
if (validation.valid) {
console.log('License is valid');
// Check specific features
if (license.hasFeature('premium_features')) {
// Enable premium features
}
}Configuration
LicenseConfig Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| encryptedProductId | string | required | Encrypted product identifier (use createEncryptedProductId()) |
| licenseKey | string | from config | License key (loaded from config file if not provided) |
| configPath | string | auto-detect | Path to config file (.env, license.config.json, or license.config.js) |
| storagePath | string | '.license' | Path to store activation data |
| offlineGracePeriod | number | 7 | Days before requiring online validation |
| heartbeatInterval | number | 24 | Hours between automatic validations |
| autoHeartbeat | boolean | true | Enable automatic background validation |
| timeout | number | 10000 | API request timeout in milliseconds |
| debug | boolean | false | Enable debug logging |
| publicKey | string | '' | Public key for offline validation |
Note: The API URL is encrypted and built into the package. It cannot be changed without rebuilding the package.
API Reference
LicenseClient
Methods
activate(licenseKey?: string): Promise<ActivationResult>
Activate the license on the current device.
const result = await license.activate('XXXX-XXXX-XXXX-XXXX');
if (result.success) {
console.log('Activated!', result.activationData);
} else {
console.error('Activation failed:', result.message);
}deactivate(): Promise<{ success: boolean; message: string }>
Deactivate the license from the current device.
const result = await license.deactivate();
console.log(result.message);validate(): Promise<ValidationResult>
Validate the license (tries online first, falls back to offline).
const result = await license.validate();
if (result.valid) {
console.log('License is valid');
if (result.offline) {
console.log('Validated offline');
}
} else {
console.error('Invalid license:', result.message);
}heartbeat(): Promise<HeartbeatResult>
Manually send a heartbeat to verify the license.
const result = await license.heartbeat();
console.log('License valid:', result.licenseValid);getStatus(): LicenseStatus
Get comprehensive license status information.
const status = license.getStatus();
console.log('Valid:', status.isValid);
console.log('Activated:', status.isActivated);
console.log('Days until expiration:', status.daysUntilExpiration);
console.log('In grace period:', status.inGracePeriod);hasFeature(featureName: string): boolean
Check if a specific feature is enabled.
if (license.hasFeature('advanced_reporting')) {
// Show advanced reporting features
}
if (license.hasFeature('api_access')) {
// Enable API access
}getLicenseInfo(): LicenseInfo | null
Get detailed license information.
const info = license.getLicenseInfo();
if (info) {
console.log('License type:', info.licenseType);
console.log('Expires:', info.expiresAt);
console.log('Features:', info.features);
console.log('Activations:', info.activationsUsed, '/', info.activationLimit);
}isActivated(): boolean
Check if license is currently activated.
if (!license.isActivated()) {
// Show activation prompt
}on(eventType: LicenseEventType, callback: LicenseEventCallback): void
Subscribe to license events.
license.on('activated', (event) => {
console.log('License activated!', event.data);
});
license.on('expired', (event) => {
console.log('License expired!');
// Show renewal prompt
});
license.on('revoked', (event) => {
console.log('License was revoked');
// Disable application
});
license.on('grace_period', (event) => {
if (event.data.expired) {
console.log('Grace period expired - please connect to internet');
}
});destroy(): void
Clean up resources (stop heartbeat, clear event listeners).
license.destroy();Event Types
activated- License was successfully activateddeactivated- License was deactivatedvalidated- License validation completedexpired- License has expiredrevoked- License was revokedheartbeat- Heartbeat verification completederror- An error occurredgrace_period- Grace period status changed
Usage Examples
Basic Application Protection
import { LicenseClient } from '@yourorg/license-client';
async function initializeApp() {
const license = new LicenseClient({
apiUrl: 'https://license.yourapp.com',
productId: 'my-app',
licenseKey: process.env.LICENSE_KEY
});
// Check if already activated
if (!license.isActivated()) {
console.log('Please activate your license');
const result = await license.activate();
if (!result.success) {
console.error('Activation failed:', result.message);
process.exit(1);
}
}
// Validate license
const validation = await license.validate();
if (!validation.valid) {
console.error('Invalid license:', validation.message);
process.exit(1);
}
console.log('Application started with valid license');
// Start your application
startApplication();
}
initializeApp();Feature-Gated Application
const license = new LicenseClient({
apiUrl: 'https://license.yourapp.com',
productId: 'my-app'
});
// Check license tier and enable features accordingly
const status = license.getStatus();
if (status.isValid) {
const info = license.getLicenseInfo();
console.log(`Welcome! You have a ${info.licenseType} license`);
// Enable features based on license
const features = {
basicFeatures: true,
advancedReporting: license.hasFeature('advanced_reporting'),
apiAccess: license.hasFeature('api_access'),
customBranding: license.hasFeature('custom_branding'),
multiUser: license.hasFeature('multi_user_support')
};
startApplication(features);
}CLI Tool with License Management
import { LicenseClient } from '@yourorg/license-client';
import * as readline from 'readline';
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const license = new LicenseClient({
apiUrl: 'https://license.yourapp.com',
productId: 'my-cli-tool'
});
async function promptForLicense() {
return new Promise<string>((resolve) => {
rl.question('Enter your license key: ', (key) => {
resolve(key);
});
});
}
async function main() {
if (!license.isActivated()) {
const key = await promptForLicense();
const result = await license.activate(key);
if (result.success) {
console.log('✓ License activated successfully!');
} else {
console.error('✗ Activation failed:', result.message);
process.exit(1);
}
}
const validation = await license.validate();
if (!validation.valid) {
console.error('✗ License is invalid:', validation.message);
if (validation.errorCode === 'GRACE_PERIOD_EXPIRED') {
console.log('Please connect to the internet to verify your license');
}
process.exit(1);
}
// Run your CLI tool
runCLITool();
rl.close();
}
main();Web Server with License Validation
import express from 'express';
import { LicenseClient } from '@yourorg/license-client';
const app = express();
const license = new LicenseClient({
apiUrl: 'https://license.yourapp.com',
productId: 'my-web-service',
licenseKey: process.env.LICENSE_KEY
});
// Middleware to check license
app.use(async (req, res, next) => {
const status = license.getStatus();
if (!status.isValid) {
return res.status(403).json({
error: 'Invalid or expired license',
message: 'Please contact support to renew your license'
});
}
next();
});
// Feature-gated endpoints
app.get('/api/advanced-report', (req, res) => {
if (!license.hasFeature('advanced_reporting')) {
return res.status(403).json({
error: 'Feature not available',
message: 'Upgrade your license to access advanced reporting'
});
}
// Generate advanced report
res.json({ report: 'Advanced report data...' });
});
app.listen(3000, async () => {
// Validate license on startup
const validation = await license.validate();
if (!validation.valid) {
console.error('Invalid license - server will not start');
process.exit(1);
}
console.log('Server running with valid license');
});Desktop Application with UI
import { LicenseClient } from '@yourorg/license-client';
const license = new LicenseClient({
apiUrl: 'https://license.yourapp.com',
productId: 'my-desktop-app',
debug: true
});
// Listen to license events and update UI
license.on('activated', (event) => {
showNotification('License activated successfully!');
updateUIForValidLicense();
});
license.on('expired', (event) => {
showNotification('Your license has expired', 'warning');
showRenewalDialog();
});
license.on('grace_period', (event) => {
if (event.data.expired) {
showNotification('Please connect to internet to verify license', 'warning');
}
});
// Check status periodically and update UI
setInterval(() => {
const status = license.getStatus();
updateStatusBar(status);
if (status.daysUntilExpiration !== null && status.daysUntilExpiration <= 7) {
showExpirationWarning(status.daysUntilExpiration);
}
}, 60000); // Every minute
function updateStatusBar(status: LicenseStatus) {
const statusElement = document.getElementById('license-status');
if (status.isValid) {
const info = license.getLicenseInfo();
statusElement.textContent = `License: ${info.licenseType} - Valid`;
statusElement.className = 'status-valid';
} else {
statusElement.textContent = 'License: Invalid';
statusElement.className = 'status-invalid';
}
}Types
LicenseInfo
interface LicenseInfo {
licenseKey: string;
licenseType: 'trial' | 'basic' | 'pro' | 'enterprise' | 'lifetime';
status: 'active' | 'expired' | 'suspended' | 'revoked';
productId: string;
customerEmail?: string;
customerName?: string;
activationLimit: number;
activationsUsed: number;
createdAt: Date;
activatedAt?: Date;
expiresAt?: Date;
features: string[];
metadata?: Record<string, any>;
}LicenseStatus
interface LicenseStatus {
isValid: boolean;
isActivated: boolean;
licenseInfo?: LicenseInfo;
daysUntilExpiration?: number | null;
remainingActivations?: number;
lastVerified?: Date;
daysSinceVerification?: number;
inGracePeriod: boolean;
}Error Handling
The library provides specific error classes for different scenarios:
import {
LicenseError,
LicenseValidationError,
LicenseActivationError,
LicenseExpiredError,
LicenseRevokedError,
NetworkError
} from '@yourorg/license-client';
try {
const result = await license.activate();
} catch (error) {
if (error instanceof LicenseExpiredError) {
console.log('License has expired - show renewal options');
} else if (error instanceof LicenseRevokedError) {
console.log('License was revoked - contact support');
} else if (error instanceof NetworkError) {
console.log('Network error - try offline validation');
} else if (error instanceof LicenseError) {
console.log('License error:', error.code, error.message);
}
}Best Practices
- Store License Keys Securely - Never hardcode license keys in your source code
- Graceful Degradation - Handle offline scenarios gracefully
- User Feedback - Provide clear messages about license status
- Event Handling - Listen to license events to update UI
- Error Handling - Catch and handle license errors appropriately
- Periodic Checks - Validate license periodically during application runtime
- Clean Shutdown - Call
destroy()when your application exits
Security Notes
- Activation data is stored locally in
.licensefile by default - Device fingerprinting uses multiple hardware identifiers
- Offline validation uses cryptographic token verification
- All API communications should use HTTPS
- Activation tokens are signed and verified
- Grace period prevents abuse of offline mode
Server Requirements
This client library requires a compatible license server. The server must provide these endpoints:
POST /api/license/activate- Activate a licensePOST /api/license/deactivate- Deactivate a licensePOST /api/license/validate- Validate a licensePOST /api/license/verify-heartbeat- Verify license heartbeat
Documentation
- USER-GUIDE.md - Complete user guide for integrating the package
- EXAMPLES.md - Real-world code examples for different app types
- QUICK-START.md - Get started in 5 minutes
- CONFIGURATION.md - Interactive configuration guide
- USAGE.md - Detailed usage guide with encryption
- INTEGRATION.md - Framework-specific examples
- WEBSOCKET-TELEMETRY.md - Real-time updates and telemetry
- API-REFERENCE.md - Complete JSON API documentation
- BUILD.md - Build and publish guide
- SUMMARY.md - Package overview and architecture
License
MIT License - see LICENSE file for details
Support
For issues, questions, or contributions, please visit: https://github.com/yourorg/license-client
Changelog
1.0.0
- Initial release
- Online and offline validation
- Hardware fingerprinting
- Automatic heartbeat
- Event system
- TypeScript support
