Documentation Index
Fetch the complete documentation index at: https://docs.authforge.cc/llms.txt
Use this file to discover all available pages before exploring further.
Requirements
- Node.js 18.0 or later
- No runtime dependencies beyond Node.js built-ins
Installation
Install from npm as @authforgecc/sdk:
npm install @authforgecc/sdk
The package ships authforge.mjs and TypeScript declarations (authforge.d.ts).
Prefer a single file in-repo? Copy authforge.mjs from GitHub. The npm package is recommended for versioning and updates.
TypeScript
Use the same import as JavaScript; types resolve from the package:
import { AuthForgeClient } from "@authforgecc/sdk";
Quick start
import { AuthForgeClient } from "@authforgecc/sdk";
import * as readline from "node:readline/promises";
const client = new AuthForgeClient({
appId: "YOUR_APP_ID",
appSecret: "YOUR_APP_SECRET",
publicKey: "YOUR_PUBLIC_KEY",
heartbeatMode: "SERVER",
});
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const key = await rl.question("Enter license key: ");
rl.close();
if (await client.login(key)) {
console.log("Authenticated!");
// Your app logic here - heartbeats run in the background
} else {
console.error("Invalid license key.");
process.exit(1);
}
Constructor parameters
const client = new AuthForgeClient({
appId: "YOUR_APP_ID", // Required - from dashboard
appSecret: "YOUR_APP_SECRET", // Required - from dashboard
publicKey: "YOUR_PUBLIC_KEY", // Required - Ed25519 public key from your AuthForge dashboard (base64)
heartbeatMode: "SERVER", // Required - "SERVER" or "LOCAL"
heartbeatInterval: 900, // Optional - seconds (default: 900 = 15 min, any value ≥ 1 is supported)
apiBaseUrl: "https://auth.authforge.cc", // Optional
onFailure: null, // Optional - callback(reason, exception)
requestTimeout: 15, // Optional - HTTP timeout in seconds
ttlSeconds: null, // Optional - requested session TTL. null = server default (24h). Clamped to [3600, 604800].
hwidOverride: null, // Optional - custom identity (for example "tg:123456789")
});
ttlSeconds
Requested session token lifetime in seconds for /auth/validate. Pass null (or omit) to accept the server default of 24 hours. The server clamps to [3600, 604800] (1 hour to 7 days). The requested TTL is preserved across heartbeat refreshes so long-running apps in LOCAL mode can stretch their offline window up to 7 days.
Billing
- Each successful
login() or validateLicense() costs 1 credit (one /auth/validate debit).
- Heartbeats cost 1 credit per 10 successful calls (billed on every 10th heartbeat). Any
heartbeatInterval ≥ 1 is economically safe.
- Revocations take effect on the next heartbeat regardless of interval.
Login
const success = await client.login(licenseKey);
Returns Promise<boolean>. It resolves to true if authentication succeeded, false otherwise. On success, the SDK starts background heartbeats automatically.
Validate license (no heartbeat)
const result = await client.validateLicense(licenseKey);
if (result.valid) {
console.log(result.sessionToken, result.expiresIn, result.appVariables, result.licenseVariables);
} else {
console.error(result.code, result.error);
}
Same /auth/validate request and Ed25519 verification as login, without mutating the client’s stored session or starting the heartbeat timer. Use this for bots and repeated checks; use login when you want background heartbeats. Successful results may also include sessionExpiresAt, licenseExpiresAt (null for lifetime keys), maxHwidSlots, hwidCount, and licenseLabel when present in the signed payload; the decoded payload is always available as sessionData.
Failure callback
If authentication or a heartbeat fails, the SDK calls your onFailure callback. If no callback is set (or the callback throws), the SDK exits the process.
function handleFailure(reason, exception) {
if (reason === "login_failed") {
console.error("Login failed - check your license key.");
return;
}
if (reason === "heartbeat_failed") {
console.error("Heartbeat failed - saving state and shutting down.");
saveApplicationState();
}
}
const client = new AuthForgeClient({
appId: "YOUR_APP_ID",
appSecret: "YOUR_APP_SECRET",
publicKey: "YOUR_PUBLIC_KEY",
heartbeatMode: "SERVER",
onFailure: handleFailure,
});
If you don’t set onFailure, the SDK terminates the process immediately on any failure. Set a callback in production for graceful shutdown.
Reading variables
After successful login, app variables and license variables are available on the client:
if (await client.login(licenseKey)) {
// App-wide variables (set in dashboard or API)
const appVars = client.appVariables;
if (appVars.maintenanceMode) {
console.log("Server is under maintenance.");
process.exit(0);
}
// Per-license variables
const plan = client.licenseVariables.plan ?? "basic";
if (plan === "pro") {
enableProFeatures();
}
}
Heartbeat modes
// SERVER mode - validates with the API every interval
const serverClient = new AuthForgeClient({
appId: "YOUR_APP_ID",
appSecret: "YOUR_APP_SECRET",
publicKey: "YOUR_PUBLIC_KEY",
heartbeatMode: "SERVER",
heartbeatInterval: 900,
});
// LOCAL mode - verifies locally, re-validates when the session token expires (default 24h; up to 7d via ttlSeconds)
const localClient = new AuthForgeClient({
appId: "YOUR_APP_ID",
appSecret: "YOUR_APP_SECRET",
publicKey: "YOUR_PUBLIC_KEY",
heartbeatMode: "LOCAL",
heartbeatInterval: 900,
});
See Heartbeat Modes for a detailed comparison.
Full example
import { AuthForgeClient } from "@authforgecc/sdk";
import * as readline from "node:readline/promises";
function saveState() {
console.log("Saving application state...");
// Your save logic here
}
const client = new AuthForgeClient({
appId: "YOUR_APP_ID",
appSecret: "YOUR_APP_SECRET",
publicKey: "YOUR_PUBLIC_KEY",
heartbeatMode: "SERVER",
heartbeatInterval: 900,
onFailure: (reason, exception) => {
console.error(`Auth failure: ${reason}`);
if (exception) {
console.error(`Detail: ${exception.message ?? exception}`);
}
saveState();
process.exit(1);
},
});
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const key = await rl.question("Enter license key: ");
rl.close();
if (!(await client.login(key))) {
console.error("Invalid license key.");
process.exit(1);
}
console.log("Licensed and running!");
const minVersion = client.appVariables.minVersion;
if (minVersion && APP_VERSION < minVersion) {
console.error(`Please update to version ${minVersion} or later.`);
process.exit(1);
}
process.on("SIGINT", () => {
saveState();
process.exit(0);
});
setInterval(() => {
// Your app logic here
}, 1000);
GitHub
Full source, changelog, and issues: AuthForgeCC/authforge-node