This file is optimized for AI coding agents (Cursor, Copilot, Claude Code, etc.). It contains everything needed to correctly integrate AuthForge licensing into a project.
AuthForge is a license key validation service. Your app sends a license key + hardware ID to the AuthForge API, gets back a cryptographically signed response, and runs background heartbeats to maintain the session. If the license is revoked or expired, the heartbeat fails and you handle it (typically exit the app).
Add authforge_sdk.h and authforge_sdk.cpp to your project, or consume the library via CMake find_package after installing from source (see README). Requires C++17, libsodium, OpenSSL, and libcurl.
#include "authforge_sdk.h"
#include <cstdlib>
#include <iostream>
#include <string>
int main() {
authforge::AuthForgeClient client(
"YOUR_APP_ID",
"YOUR_APP_SECRET",
"SERVER",
900,
authforge::AuthForgeClient::kDefaultApiBaseUrl,
[](const std::string &reason, const std::exception *exc) {
std::cerr << "AuthForge: " << reason << "\n";
if (exc) std::cerr << exc->what() << "\n";
std::exit(1);
});
std::string license_key;
std::cout << "Enter license key: ";
std::getline(std::cin, license_key);
if (!client.Login(license_key)) {
std::cerr << "Login failed.\n";
return 1;
}
// --- Your application code starts here ---
std::cout << "Running with a valid license.\n";
// --- Your application code ends here ---
client.Logout();
return 0;
}| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
appId |
std::string |
yes | — | Application ID |
appSecret |
std::string |
yes | — | Application secret |
heartbeatMode |
std::string |
yes | — | "SERVER" or "LOCAL" |
heartbeatInterval |
int |
no | 900 |
Seconds between heartbeats (minimum 10; revocations apply on the next heartbeat) |
apiBaseUrl |
std::string |
no | kDefaultApiBaseUrl (https://auth.authforge.cc) |
API base URL |
onFailure |
std::function<void(const std::string&, const std::exception*)> |
no | nullptr |
Failure callback for Login / heartbeat; if null, std::exit(1) (not used by ValidateLicense) |
requestTimeout |
int |
no | 15 |
HTTP timeout (seconds) |
ttlSeconds |
int |
no | 0 (server default: 86400) |
Requested session token lifetime. 0 means "server default". Server clamps to [3600, 604800]; preserved across heartbeat refreshes. |
hwidOverride |
std::string |
no | "" |
Optional custom HWID/subject string. When non-empty (for example tg:123456789), the SDK sends it instead of generating a machine fingerprint. |
For Telegram/Discord bot flows, prefer immutable IDs (tg:<user_id>, discord:<user_id>) instead of usernames.
- Each
Login()orValidateLicense()calls/auth/validateand costs 1 credit. - Heartbeats cost 1 credit per 10 successful calls (billed on every 10th heartbeat).
- Keep heartbeat interval at or above 10 seconds.
/auth/heartbeatis limited to 6 requests/minute per license key; cost still scales with how many heartbeats you send. - Revocations take effect on the next heartbeat regardless of interval.
| Method | Returns | Description |
|---|---|---|
Login(const std::string&) |
bool |
Validates license and starts heartbeat |
ValidateLicense(const std::string&) |
ValidateLicenseResult |
Same validate + signatures; no session/heartbeat; never calls onFailure or std::exit |
Logout() |
void |
Stops heartbeat and clears state |
IsAuthenticated() |
bool |
Whether authenticated |
GetSessionDataJson() |
std::optional<std::string> |
Payload JSON string |
GetAppVariablesJson() |
std::optional<std::string> |
App variables JSON |
GetLicenseVariablesJson() |
std::optional<std::string> |
License variables JSON |
invalid_app, invalid_key, expired, revoked, hwid_mismatch, no_credits, blocked, rate_limited, replay_detected, session_expired, app_disabled, bad_request
Notes:
replay_detectedis validate-only.rate_limitedcan be returned by/auth/validateand/auth/heartbeat(heartbeat is license-limited at 6/min and has no app-layer IP limit).
if (auto json = client.GetLicenseVariablesJson()) {
std::cout << "licenseVariables=" << *json << "\n";
}Parse the JSON string with your JSON library, then read keys for gating.
client.Logout();Use the onFailure callback; distinguish reason (login_failed, heartbeat_failed, network_error) and inspect exc when non-null.
- Do not hardcode the app secret as a plain string literal in source — use environment variables or encrypted config
- Do not omit
onFailure— without it, failures callstd::exit(1)without your cleanup - Do not call
Loginon every app action — call once at startup; heartbeats handle the rest - Do not use
heartbeatMode"LOCAL"unless the app has no internet after initial auth