Node.js SDK
The official TigerIdentity SDK for Node.js and TypeScript. Full type safety, promise-based APIs, and seamless Express/Fastify integration.
Installation
Install the SDK using npm:
npm install @tigeridentity/sdk
Or using yarn:
yarn add @tigeridentity/sdk
Or using pnpm:
pnpm add @tigeridentity/sdk
Requirements: Node.js 16.x or higher
Quick Start
Initialize the client with TypeScript and make your first access decision:
import { TigerClient } from '@tigeridentity/sdk';
// Initialize client
const client = new TigerClient({
apiKey: 'your-api-key',
baseURL: 'https://api.tigeridentity.com',
});
// Evaluate access
const result = await client.decisions.evaluate({
principalId: 'user-123',
action: 'read',
resource: 'document:sensitive-report',
context: {
ipAddress: '203.0.113.42',
deviceTrust: 'high',
mfaVerified: true,
},
});
if (result.allowed) {
console.log(`Access granted: ${result.reason}`);
} else {
console.log(`Access denied: ${result.reason}`);
}
// List principals
const principals = await client.principals.list({
type: 'user',
limit: 50,
});
principals.items.forEach((principal) => {
console.log(`Principal: ${principal.id} (${principal.type})`);
});Key Classes
TigerClient
Main client class with automatic retries, connection pooling, and built-in caching.
new TigerClient(options)DecisionClient
Real-time access decisions with context evaluation and caching support.
client.decisions.evaluate()PrincipalClient
Identity management for users, services, and AI agents with full CRUD operations.
client.principals.get()PolicyClient
Create, update, and simulate access policies with versioning and rollback.
client.policies.create()EventClient
Subscribe to CAEP events for real-time security notifications.
client.events.subscribe()WebhookClient
Manage webhooks and verify webhook signatures for security.
client.webhooks.verify()Usage Examples
Creating a Policy
import { PolicyEffect, ConditionOperator } from '@tigeridentity/sdk';
// Create a geo-fencing policy
const policy = await client.policies.create({
name: 'geo-restricted-access',
description: 'Restrict access based on geographic location',
rules: [
{
effect: PolicyEffect.Allow,
conditions: [
{
field: 'context.location.country',
operator: ConditionOperator.In,
value: ['US', 'CA', 'GB'],
},
{
field: 'context.vpn',
operator: ConditionOperator.Equals,
value: false,
},
],
},
],
resources: ['customer:*', 'order:*'],
actions: ['read', 'write'],
});
console.log(`Created policy: ${policy.id}`);Express Middleware
import express from 'express';
import { TigerClient } from '@tigeridentity/sdk';
const app = express();
const tiger = new TigerClient({ apiKey: process.env.TIGER_API_KEY });
// Middleware to check access
function requireAccess(action: string, resourceFn: (req: any) => string) {
return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
const resource = resourceFn(req);
const principalId = `user-${req.user?.id}`;
try {
const result = await tiger.decisions.evaluate({
principalId,
action,
resource,
context: {
ipAddress: req.ip,
userAgent: req.get('user-agent'),
path: req.path,
},
});
if (!result.allowed) {
return res.status(403).json({
error: 'Access denied',
reason: result.reason,
});
}
next();
} catch (error) {
console.error('Access check failed:', error);
res.status(500).json({ error: 'Internal server error' });
}
};
}
// Protected routes
app.get(
'/projects/:id',
requireAccess('read', (req) => `project:${req.params.id}`)
);
app.delete(
'/projects/:id',
requireAccess('delete', (req) => `project:${req.params.id}`)
);
app.listen(3000);Webhook Handler
import { TigerClient, WebhookEvent, WebhookEventType } from '@tigeridentity/sdk';
const tiger = new TigerClient({ apiKey: process.env.TIGER_API_KEY });
// Express webhook endpoint
app.post('/webhooks/tiger', async (req, res) => {
const signature = req.get('x-tiger-signature');
const timestamp = req.get('x-tiger-timestamp');
try {
// Verify webhook signature
const isValid = tiger.webhooks.verify({
payload: JSON.stringify(req.body),
signature: signature!,
timestamp: timestamp!,
secret: process.env.TIGER_WEBHOOK_SECRET!,
});
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event: WebhookEvent = req.body;
// Handle different event types
switch (event.type) {
case WebhookEventType.SessionRevoked:
console.log(`Session revoked: ${event.data.sessionId}`);
// Invalidate local session cache
await invalidateSession(event.data.sessionId);
break;
case WebhookEventType.RiskScoreChanged:
console.log(`Risk score changed: ${event.data.principalId}`);
// Re-evaluate active sessions
await reevaluateUserSessions(event.data.principalId);
break;
case WebhookEventType.PrincipalDisabled:
console.log(`Principal disabled: ${event.data.principalId}`);
// Terminate all sessions
await terminateAllSessions(event.data.principalId);
break;
case WebhookEventType.PolicyUpdated:
console.log(`Policy updated: ${event.data.policyId}`);
// Clear policy cache
await clearPolicyCache();
break;
}
res.json({ received: true });
} catch (error) {
console.error('Webhook error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});Batch Operations
// Evaluate multiple access requests in parallel
const requests = [
{
principalId: 'user-alice',
action: 'read',
resource: 'project:alpha',
},
{
principalId: 'user-alice',
action: 'write',
resource: 'project:alpha',
},
{
principalId: 'user-alice',
action: 'delete',
resource: 'project:alpha',
},
];
const results = await client.decisions.batchEvaluate({
requests,
});
results.results.forEach((result, index) => {
const action = requests[index].action;
console.log(`${action}: ${result.allowed ? '✓' : '✗'}`);
if (!result.allowed) {
console.log(` Reason: ${result.reason}`);
}
});
// Create multiple principals at once
const principals = await Promise.all([
client.principals.create({
type: 'user',
id: 'user-new-hire-1',
attributes: {
email: '[email protected]',
department: 'engineering',
},
}),
client.principals.create({
type: 'user',
id: 'user-new-hire-2',
attributes: {
email: '[email protected]',
department: 'engineering',
},
}),
]);
console.log(`Created ${principals.length} principals`);TypeScript Support
The SDK includes full TypeScript definitions for type-safe development:
import {
TigerClient,
EvaluateRequest,
EvaluateResult,
Principal,
PrincipalType,
Policy,
PolicyEffect,
ConditionOperator,
} from '@tigeridentity/sdk';
// Type-safe request
const request: EvaluateRequest = {
principalId: 'user-123',
action: 'read',
resource: 'document:123',
context: {
ipAddress: '192.168.1.1',
// TypeScript ensures correct types
},
};
// Type-safe response
const result: EvaluateResult = await client.decisions.evaluate(request);
// Strongly typed enums
const userType: PrincipalType = PrincipalType.User;
const effect: PolicyEffect = PolicyEffect.Allow;
const operator: ConditionOperator = ConditionOperator.Equals;Error Handling
import {
TigerIdentityError,
APIError,
NotFoundError,
RateLimitError,
UnauthorizedError,
} from '@tigeridentity/sdk';
try {
const result = await client.decisions.evaluate(request);
} catch (error) {
if (error instanceof NotFoundError) {
console.error(`Principal not found: ${error.message}`);
} else if (error instanceof RateLimitError) {
console.error(`Rate limited. Retry after ${error.retryAfter}s`);
await new Promise((resolve) => setTimeout(resolve, error.retryAfter * 1000));
} else if (error instanceof UnauthorizedError) {
console.error('Invalid API key');
} else if (error instanceof APIError) {
console.error(`API error: ${error.message} (code: ${error.code})`);
} else if (error instanceof TigerIdentityError) {
console.error(`SDK error: ${error.message}`);
} else {
console.error('Unexpected error:', error);
}
}Start building with Node.js
Get your API key and integrate TigerIdentity in minutes.