Skip to main content
This is the most important page in the documentation. Read it before shipping your integration.

License key input UX

Desktop apps

Use a dialog or popup window on first launch. After successful validation, store the key locally (e.g., in a config file, registry, or app data directory) so users don’t re-enter it every time. Provide a “Deactivate” or “Change License” option in settings.

Enter License Key

XXXX-XXXX-XXXX-XXXX
PurchaseActivate

CLI tools

Support multiple input methods:
  1. Command-line flag: --license-key XXXX-XXXX-XXXX-XXXX
  2. Environment variable: AUTHFORGE_LICENSE_KEY
  3. Config file: ~/.yourapp/config.json or ~/.yourapp/license
  4. Interactive prompt: Ask on first run if no key is found

Game mods and plugins

Read the key from a config file in the mod/plugin directory (e.g., plugins/your-mod/license.txt or config.yml). Don’t block the game’s main thread with a dialog; load the key at plugin initialization and fail gracefully.

Error handling on login

Handle each error code with an appropriate user-facing message. Never expose internal details to end users.
Never expose no_credits to end users; this is your billing issue, not theirs. Show a generic “temporarily unavailable” message.

Go

Use errors.Is against the exported authforge.Err* values (Go SDK; Error handling). If go build fails while compiling the SDK with undefined: errors, your authforge.go is out of date: the module must import the standard errors package for those sentinels. Pull the latest SDK sources (see the note on Go SDK; Installation).

Network error retry

On network failures, retry 2–3 times with exponential backoff before giving up:

Heartbeat failure handling

Don’t kill the app immediately. The user could lose unsaved work. A heartbeat failure might be a momentary network blip.

The grace period pattern

When a heartbeat fails, start a countdown. Show a non-intrusive warning. If the next heartbeat succeeds, cancel the countdown.

Application-specific behavior

Always save before terminating


The onFailure callback pattern

Every SDK language follows the same pattern. Your callback receives a reason string and an optional exception:

Offline and poor connectivity

When to use LOCAL heartbeat mode

LOCAL mode is designed for applications where users may not always have internet access:
  • The initial login() call always requires network; make this clear in your app’s system requirements.
  • After login, LOCAL mode verifies the stored signature locally without network calls.
  • In SERVER mode, each successful heartbeat extends the session automatically; long-running apps stay authenticated indefinitely as long as heartbeats succeed.
  • In LOCAL mode, the session expires when the session token’s TTL elapses (default 24 hours; configurable via the SDK’s ttlSeconds / session_ttl_seconds / SessionTTL option, up to 7 days). Revocations don’t take effect until the SDK makes a new server call.

SERVER mode tolerance

Even in SERVER mode, individual heartbeat failures don’t immediately trigger shutdown (the SDK handles this internally). The failure callback fires when the SDK determines the session is truly invalid; not on every transient network blip. First launch always requires network. Document this in your app’s requirements.

Multi-instance and multi-window

If your app can be opened multiple times on the same machine:
  • Only one instance should authenticate. Use a lockfile or IPC mechanism to coordinate.
  • All instances share the same HWID, so extra instances won’t consume HWID slots.
  • Each login() call consumes a credit. If your app opens 10 windows, don’t call login 10 times.

Version updates

  • The same license keys work across all versions of your app. You don’t need to regenerate keys when pushing an update.
  • Use app variables to enforce a minimum version:

Anti-tampering tips

1

Protect your App Secret

Don’t log the app secret anywhere. Don’t store it in plain text in the binary. Use environment variables or encrypted configuration.
2

Authenticate early

Call login() early in your app’s startup, not lazily. Don’t let the app run unprotected code paths before authentication.
3

Minimize error details

Don’t expose internal auth failure details to the user. “The signature check failed” helps attackers; just say “Authentication failed.”
4

Don't trust the client

Assume the binary can be modified. Critical business logic that depends on license status should check variables, not just a boolean flag.
5

Use SERVER heartbeat mode for high-value software

LOCAL mode can be bypassed by freezing the system clock. SERVER mode requires a valid signed response from the API.