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

  • .NET 6.0 or later
  • BouncyCastle.Cryptography (pulled in transitively with the AuthForge package)

Installation

Add the AuthForge package from NuGet:
dotnet add package AuthForge
Prefer a source-only layout? Copy AuthForgeClient.cs from GitHub and reference BouncyCastle.Cryptography explicitly. The NuGet package is recommended for most apps.

Quick start

using AuthForge;

var client = new AuthForgeClient(
    appId: "YOUR_APP_ID",
    appSecret: "YOUR_APP_SECRET",
    publicKey: "YOUR_PUBLIC_KEY",
    heartbeatMode: "SERVER"
);

Console.Write("Enter license key: ");
var key = Console.ReadLine() ?? "";

if (client.Login(key))
{
    Console.WriteLine("Authenticated!");
    // Your app logic here; heartbeats run in the background
}
else
{
    Console.WriteLine("Invalid license key.");
    Environment.Exit(1);
}

Constructor parameters

var client = new AuthForgeClient(
    appId: "...",                   // Required; from dashboard
    appSecret: "...",               // 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, any value ≥ 1 is supported)
    apiBaseUrl: "https://auth.authforge.cc",  // Optional
    onFailure: null,                // Optional; Action<string, 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 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 heartbeatInterval ≥ 1 is economically safe.
  • Revocations take effect on the next heartbeat regardless of interval.

Login

bool success = client.Login(licenseKey);
Returns true if authentication succeeded, false otherwise. On success, the SDK starts a background heartbeat thread automatically.

Validate license (no heartbeat)

var result = client.ValidateLicense(licenseKey);
if (result.Valid) {
    Console.WriteLine(result.SessionToken);
} else {
    Console.WriteLine(result.ErrorCode);
}
Same /auth/validate request and verification as Login, without updating the client’s session fields or starting the heartbeat thread.

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 calls Environment.Exit(1).
void HandleFailure(string reason, Exception? exception)
{
    if (reason == "login_failed")
    {
        Console.WriteLine("Login failed; check your license key.");
    }
    else if (reason == "heartbeat_failed")
    {
        Console.WriteLine("Heartbeat failed; saving state.");
        SaveApplicationState();
    }
}

var 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. Always set a callback in production to handle graceful shutdown.

Reading variables

After a successful login, app variables and license variables are available:
if (client.Login(licenseKey))
{
    // App-wide variables
    var appVars = client.AppVariables;
    if (appVars.TryGetValue("maintenanceMode", out var maintenance) && maintenance is true)
    {
        Console.WriteLine("Server is under maintenance.");
        Environment.Exit(0);
    }

    // Per-license variables
    var plan = client.LicenseVariables.GetValueOrDefault("plan", "basic");
    if (plan?.ToString() == "pro")
    {
        EnableProFeatures();
    }
}

Heartbeat modes

// SERVER mode; pings the API every interval
var client = new AuthForgeClient(
    appId: "...",
    appSecret: "...",
    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)
var client = new AuthForgeClient(
    appId: "...",
    appSecret: "...",
    publicKey: "YOUR_PUBLIC_KEY",
    heartbeatMode: "LOCAL",
    heartbeatInterval: 900
);
See Heartbeat Modes for a detailed comparison.

Full example (WPF)

using System.Windows;
using AuthForge;

public partial class App : Application
{
    private AuthForgeClient? _authClient;

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        _authClient = new AuthForgeClient(
            appId: "YOUR_APP_ID",
            appSecret: "YOUR_APP_SECRET",
            publicKey: "YOUR_PUBLIC_KEY",
            heartbeatMode: "SERVER",
            onFailure: OnAuthFailure
        );

        var dialog = new LicenseDialog();
        if (dialog.ShowDialog() != true)
        {
            Shutdown();
            return;
        }

        if (!_authClient.Login(dialog.LicenseKey))
        {
            MessageBox.Show("Invalid license key.", "Authentication Failed",
                MessageBoxButton.OK, MessageBoxImage.Error);
            Shutdown();
            return;
        }

        var mainWindow = new MainWindow();
        mainWindow.Show();
    }

    private void OnAuthFailure(string reason, Exception? ex)
    {
        Dispatcher.Invoke(() =>
        {
            // Save user's work before shutting down
            (MainWindow as MainWindow)?.SaveState();

            MessageBox.Show(
                "License verification failed. Your work has been saved.",
                "Authentication Error",
                MessageBoxButton.OK,
                MessageBoxImage.Warning
            );

            Shutdown();
        });
    }
}

GitHub

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