Skip to main content

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 notes

PlatformHWID sourcesNotes
WindowsGetAdaptersAddresses, WMI, GetVolumeInformationWorks out of the box with Windows SDK
Linux/sys/class/net/*/address, /proc/cpuinfo, lsblkStandard filesystem access
macOSgetifaddrs, sysctl, diskutilMay require Full Disk Access for disk serial

GitHub

Full source, changelog, and issues: AuthForgeCC/authforge-cpp