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

  • Rust 1.70 or later
  • Crates used by the SDK:
    • hmac
    • sha2
    • serde
    • serde_json
    • ureq
    • base64
    • mac_address
    • hostname

Installation

The crate is published on crates.io/crates/authforge as authforge.
cargo add authforge
Or set a semver range in Cargo.toml (for example 1.0 for compatible 1.x releases):
[dependencies]
authforge = "1.0"
[dependencies]
authforge = { git = "https://github.com/AuthForgeCC/authforge-rust" }
Optional: pin branch, tag, or rev.

Quick start

use authforge::{AuthForgeClient, AuthForgeConfig, HeartbeatMode};

fn main() {
    let client = AuthForgeClient::new(AuthForgeConfig {
        app_id: "your-app-id".into(),
        app_secret: "your-app-secret".into(),
        public_key: "YOUR_PUBLIC_KEY".into(),
        heartbeat_mode: HeartbeatMode::Server,
        on_failure: Some(Box::new(|err| {
            eprintln!("Auth failed: {}", err);
            std::process::exit(1);
        })),
        ..Default::default()
    });

    match client.login("XXXX-XXXX-XXXX-XXXX") {
        Ok(result) => {
            println!("Authenticated!");
            println!("Session expires at unix time: {}", result.expires_in);
        }
        Err(err) => {
            eprintln!("Login failed: {:?}", err);
            std::process::exit(1);
        }
    }
}

Config struct reference

AuthForgeConfig {
    app_id: "your-app-id".into(),             // Required
    app_secret: "your-app-secret".into(),     // Required
    public_key: "YOUR_PUBLIC_KEY".into(),     // Required - Ed25519 public key from your AuthForge dashboard (base64)
    heartbeat_mode: HeartbeatMode::Server,    // Local or Server
    heartbeat_interval: 900,                  // Optional, seconds (any value ≥ 1)
    api_base_url: "https://auth.authforge.cc".into(), // Optional
    on_failure: None,                         // Optional callback
    request_timeout: 15,                      // Optional, seconds
    session_ttl_seconds: None,                // Optional - requested session TTL. None = server default (24h). Clamped to [3600, 604800].
    hwid_override: None,                      // Optional - custom identity (for example "tg:123456789")
}
FieldTypeDefaultDescription
app_idStringrequiredApplication ID from your AuthForge dashboard
app_secretStringrequiredApplication secret from your AuthForge dashboard
public_keyStringrequiredEd25519 public key from your AuthForge dashboard (base64)
heartbeat_modeHeartbeatModeLocalLocal or Server heartbeat mode
heartbeat_intervalu64900Seconds between heartbeat checks (any value ≥ 1)
api_base_urlStringhttps://auth.authforge.ccAuthForge API base URL
on_failureOption<Box<dyn Fn(&str)+Send+Sync>>NoneInvoked when heartbeat fails
request_timeoutu6415Timeout for API requests
session_ttl_secondsOption<u64>None (server default: 86400)Requested session token lifetime. Server clamps to [3600, 604800]; preserved across heartbeat refreshes.
hwid_overrideOption<String>NoneOptional custom identity string sent as HWID (for example tg:123456789).

Validate license (no heartbeat)

validate_license runs the same /auth/validate request and signature checks as login, but does not store a session on the client or start the heartbeat thread. It returns the same LoginResult on success.
match client.validate_license("XXXX-XXXX-XXXX-XXXX") {
    Ok(result) => { /* use result.session_token, result.app_variables, … */ }
    Err(err) => { /* same AuthForgeError variants as login */ }
}

Billing

  • Each successful login() or validate_license() 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.

Methods reference

pub fn new(config: AuthForgeConfig) -> Self;
pub fn login(&self, license_key: &str) -> Result<LoginResult, AuthForgeError>;
pub fn validate_license(&self, license_key: &str) -> Result<LoginResult, AuthForgeError>;
pub fn logout(&self);
pub fn is_authenticated(&self) -> bool;
pub fn get_session_data(&self) -> Option<serde_json::Value>;
pub fn get_app_variables(&self) -> Option<std::collections::HashMap<String, serde_json::Value>>;
pub fn get_license_variables(&self) -> Option<std::collections::HashMap<String, serde_json::Value>>;

Error enum reference

AuthForgeError::InvalidApp
AuthForgeError::InvalidKey
AuthForgeError::Expired
AuthForgeError::Revoked
AuthForgeError::HwidMismatch
AuthForgeError::NoCredits
AuthForgeError::Blocked
AuthForgeError::RateLimited        // validate only; never returned from heartbeat
AuthForgeError::ReplayDetected     // validate only; never returned from heartbeat
AuthForgeError::SignatureMismatch
AuthForgeError::NetworkError(String)
AuthForgeError::Other(String)

Heartbeat modes

// SERVER mode: network heartbeats via /auth/heartbeat
let server_client = AuthForgeClient::new(AuthForgeConfig {
    app_id: "...".into(),
    app_secret: "...".into(),
    public_key: "YOUR_PUBLIC_KEY".into(),
    heartbeat_mode: HeartbeatMode::Server,
    ..Default::default()
});

// LOCAL mode: local expiry checks with no heartbeat network calls
let local_client = AuthForgeClient::new(AuthForgeConfig {
    app_id: "...".into(),
    app_secret: "...".into(),
    public_key: "YOUR_PUBLIC_KEY".into(),
    heartbeat_mode: HeartbeatMode::Local,
    ..Default::default()
});
See Heartbeat Modes for a detailed comparison.