$ guides / hwid-override

HWID Override

Implement identity-based binding with AuthForge by overriding HWID in SDKs.

Guide

This guide shows how to bind licenses to an external identity (Telegram/Discord user ID, account ID, etc.) by setting SDK HWID override fields.

When to use this

Use HWID override when device fingerprinting is the wrong abstraction:

  • bot users
  • web users
  • cloud workers
  • multi-tenant service identities

For desktop apps, use default machine HWID behavior.

Flow

  1. User requests access in your app/bot.
  2. Prompt for a license key.
  3. Build a stable identity string (for example tg:123456789).
  4. Initialize SDK with HWID override set to that identity.
  5. Call validateLicense() / validate_license / ValidateLicense (or login() if you want a long-lived session and heartbeats).
  6. Allow features only after success.

Prefer validate-license APIs for stateless or per-request checks (API gateways, bots, cron): they run the same /auth/validate flow and signature verification as login without starting heartbeat threads or timers.

Identity format and rules

  • Include a provider prefix (tg:, discord:, user:).
  • Use immutable IDs (platform numeric user IDs), not usernames.
  • Keep values under AuthForge limits (short strings are best).

SDK examples

Node

const client = new AuthForgeClient({
  appId: process.env.AUTHFORGE_APP_ID,
  appSecret: process.env.AUTHFORGE_APP_SECRET,
  publicKey: process.env.AUTHFORGE_PUBLIC_KEY,
  heartbeatMode: "SERVER",
  hwidOverride: `tg:${telegramUserId}`,
});

Python

client = AuthForgeClient(
    app_id=APP_ID,
    app_secret=APP_SECRET,
    public_key=PUBLIC_KEY,
    heartbeat_mode="SERVER",
    hwid_override=f"discord:{discord_user_id}",
)

Go

client, err := authforge.New(authforge.Config{
    AppID:         appID,
    AppSecret:     appSecret,
    PublicKey:     publicKey,
    HeartbeatMode: "server",
    HWIDOverride:  fmt.Sprintf("tg:%d", telegramUserID),
})

C#

var client = new AuthForgeClient(
    appId: appId,
    appSecret: appSecret,
    publicKey: publicKey,
    heartbeatMode: "SERVER",
    hwidOverride: $"discord:{discordUserId}"
);

Rust

let client = AuthForgeClient::new(AuthForgeConfig {
    app_id: app_id.into(),
    app_secret: app_secret.into(),
    public_key: public_key.into(),
    heartbeat_mode: HeartbeatMode::Server,
    hwid_override: Some(format!("tg:{telegram_user_id}")),
    ..Default::default()
});

C++

authforge::AuthForgeClient client(
    appId,
    appSecret,
    publicKey,
    "SERVER",
    900,
    authforge::AuthForgeClient::kDefaultApiBaseUrl,
    onFailure,
    15,
    0,
    "tg:" + std::to_string(telegramUserId)
);

Operational tips

  • Set sensible maxHwidSlots for your use case (often 1 for user-bound bots).
  • Provide a support flow to reset bindings when users migrate accounts.
  • If abuse is expected, combine with IP/HWID security lists and command rate limits.

Contact support

Feel free to reach out if you have questions, need help getting set up, or run into something unexpected. We'll get back to you as soon as we can.

Email us at support@authforge.cc