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
- C++17 or later
- libsodium: Ed25519 signature verification
- OpenSSL: SHA-256 and helpers
- libcurl: HTTPS requests
Installation
There is no central C++ package registry. Consume the official SDK from GitHub; AuthForgeCC/authforge-cpp (use a release tag under Releases).
Option A: FetchContent (CMake)
Pin a tag (for example v1.0.1) and link the authforge_sdk target:
include(FetchContent)
FetchContent_Declare(
authforge_cpp
GIT_REPOSITORY https://github.com/AuthForgeCC/authforge-cpp.git
GIT_TAG v1.0.1
)
FetchContent_MakeAvailable(authforge_cpp)
target_link_libraries(your_app PRIVATE authforge_sdk)
Option B: Install prefix + find_package
Build and install the SDK, then point CMake at the prefix:
git clone https://github.com/AuthForgeCC/authforge-cpp.git
cd authforge-cpp
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=../authforge-install
cmake --build build
cmake --install build
In your application:
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../authforge-install")
find_package(AuthForge CONFIG REQUIRED)
target_link_libraries(your_app PRIVATE AuthForge::authforge_sdk)
Dependencies
Install development packages for libsodium, OpenSSL, and libcurl before configuring CMake. Examples:
- Linux (Debian/Ubuntu):
sudo apt install libsodium-dev libssl-dev libcurl4-openssl-dev
- macOS (Homebrew):
brew install libsodium openssl curl; set CMAKE_PREFIX_PATH if CMake does not find Homebrew prefixes.
- Windows: Use vcpkg for
libsodium, openssl, and curl, then pass -DCMAKE_TOOLCHAIN_FILE=.../vcpkg.cmake.
Quick start
#include "authforge_sdk.h"
#include <iostream>
#include <string>
int main() {
authforge::AuthForgeClient client(
"YOUR_APP_ID",
"YOUR_APP_SECRET",
"YOUR_PUBLIC_KEY",
"SERVER"
);
std::string key;
std::cout << "Enter license key: ";
std::getline(std::cin, key);
if (client.Login(key)) {
std::cout << "Authenticated!" << std::endl;
// Your app logic here; heartbeats run in the background
} else {
std::cout << "Invalid license key." << std::endl;
return 1;
}
return 0;
}
Constructor parameters
authforge::AuthForgeClient client(
"app_id", // Required; from dashboard
"app_secret", // Required; from dashboard
"public_key", // Required; Ed25519 public key (base64)
"SERVER", // Required; "SERVER" or "LOCAL"
900, // Optional; heartbeat interval in seconds (default: 900, any value ≥ 1)
"https://auth.authforge.cc", // Optional; API base URL
on_failure_callback, // Optional; void(const std::string& reason, const std::exception* ex)
15, // Optional; HTTP timeout in seconds
0, // Optional; ttlSeconds: requested session TTL. 0 = server default (24h). Clamped to [3600, 604800].
"" // Optional; hwidOverride: custom identity (for example "tg:123456789")
);
ttlSeconds
Requested session token lifetime in seconds for /auth/validate. Pass 0 (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 extend 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 heartbeat interval ≥ 1 is economically safe.
- Revocations take effect on the next heartbeat regardless of interval.
Login
bool success = client.Login(license_key);
Returns true on success, false otherwise. Starts background heartbeats on success.
Validate license (no heartbeat)
authforge::ValidateLicenseResult r = client.ValidateLicense(license_key);
if (r.valid) {
// r.sessionToken, r.expiresIn, r.sessionDataJson, r.appVariablesJson, r.licenseVariablesJson
} else {
// r.errorCode; e.g. invalid_key, nonce_mismatch
}
Same /auth/validate request and Ed25519 verification as Login, without persisting session fields on the client or starting the heartbeat thread. Does not invoke the failure callback or std::exit on error; inspect valid / errorCode instead.
Failure callback
If no callback is set (or the callback throws), the SDK calls std::exit(1).
#include "authforge_sdk.h"
#include <iostream>
void on_failure(const std::string& reason, const std::exception* ex) {
if (reason == "login_failed") {
std::cerr << "Login failed." << std::endl;
} else if (reason == "heartbeat_failed") {
std::cerr << "Heartbeat failed; saving state." << std::endl;
save_application_state();
}
if (ex) {
std::cerr << " Detail: " << ex->what() << std::endl;
}
}
int main() {
authforge::AuthForgeClient client(
"YOUR_APP_ID",
"YOUR_APP_SECRET",
"YOUR_PUBLIC_KEY",
"SERVER",
900,
"https://auth.authforge.cc",
on_failure
);
// ...
}
If you don’t set an onFailure callback, the SDK terminates the process immediately via std::exit(1). Always set a callback in production.
Heartbeat modes
// SERVER mode; pings the API every interval
authforge::AuthForgeClient client("...", "...", "...", "SERVER");
// LOCAL mode; verifies locally, re-validates when the session token expires (default 24h; up to 7d via ttlSeconds)
authforge::AuthForgeClient client("...", "...", "...", "LOCAL");
See Heartbeat Modes for a detailed comparison.
Full example (game)
#include "authforge_sdk.h"
#include <iostream>
#include <string>
#include <atomic>
std::atomic<bool> g_licensed{false};
void on_auth_failure(const std::string& reason, const std::exception* ex) {
std::cerr << "[AuthForge] " << reason;
if (ex) std::cerr << ": " << ex->what();
std::cerr << std::endl;
g_licensed.store(false);
// Don't exit here; let the game loop handle shutdown gracefully
}
int main() {
authforge::AuthForgeClient client(
"YOUR_APP_ID",
"YOUR_APP_SECRET",
"YOUR_PUBLIC_KEY",
"SERVER",
900,
"https://auth.authforge.cc",
on_auth_failure
);
std::string key;
std::cout << "Enter license key: ";
std::getline(std::cin, key);
if (!client.Login(key)) {
std::cerr << "Invalid license key." << std::endl;
return 1;
}
g_licensed.store(true);
std::cout << "Licensed. Starting game..." << std::endl;
// Game loop
while (g_licensed.load()) {
// Update game state
// Render frame
// If g_licensed becomes false, show "license expired" dialog
}
std::cout << "License expired. Shutting down." << std::endl;
return 0;
}
| Platform | HWID sources | Notes |
|---|
| Windows | GetAdaptersAddresses, WMI, GetVolumeInformation | Works out of the box with Windows SDK |
| Linux | /sys/class/net/*/address, /proc/cpuinfo, lsblk | Standard filesystem access |
| macOS | getifaddrs, sysctl, diskutil | May require Full Disk Access for disk serial |
GitHub
Full source, changelog, and issues: AuthForgeCC/authforge-cpp