How locking works
- The SDK reads the operating system’s machine id (see below).
- The SDK hashes it together with your app id into a 64-character hex string and sends it with
POST /auth/validate. - The server stores that string as an opaque ID. If the license has free HWID slots, the new ID is bound. If all slots are full and this ID is not already bound, validation fails with
hwid_mismatch.
How the HWID is derived
Since SDK 2.0.0, every official SDK computes the HWID the same way:machineId is the operating system’s own machine id, trimmed and lowercased:
What this means in practice:
- Same value in every SDK: For the same app id and machine, Python, C#, C++, Rust, Go and Node all report the same HWID. You can collect it from one SDK and verify it in another.
- Different value per app: The app id is part of the hash, so two apps on the same machine get unrelated HWIDs.
- Stable across everyday changes: Network and Wi-Fi changes, renaming the computer, disk usage and USB devices do not change it.
- Changes on reinstall: Reinstalling the OS (Linux, Windows) or replacing the logic board (Mac) produces a new id. Cloned VMs or disk images can share one id.
- Containers: A container with no
/etc/machine-id, or one baked into the image and shared by every container, does not identify a machine. Use HWID override with an identifier you control.
legacy:<pre-2.0 fingerprint> as the machine id. Only in that fallback case can two SDKs report different HWIDs for the same machine.
The server treats the HWID as an opaque string. Bound HWIDs on a license and entries in Security lists must match the exact string the SDK sends.
Upgrading to 2.0
- Online licenses: The device binds its new HWID into a free slot. If all slots are full,
login()fails withhwid_mismatchuntil you raisemaxHwidSlotsor reset the license’s HWIDs. - Offline
.authforgefiles: A file bound to a pre-2.0 HWID fails withhwid_mismatch. Ask the customer for a new activation request from the 2.0 build and re-issue the file. - Security lists: HWID entries added from pre-2.0 SDKs no longer match. Re-add them with the new values.
- Go: The module path is now
github.com/AuthForgeCC/authforge-go/v2. Update your imports and rungo get github.com/AuthForgeCC/authforge-go/v2@latest.
Disabling seat limits
Some keys are not paid licenses - internal team tools, beta cohorts, public demos. For those, you usually want one shared key that any device can activate, with nohwid_mismatch errors and no exclusive binding. AuthForge supports this as a per-license toggle: see Unlimited-seat licenses. Activations are still logged so you keep distinct-device analytics; only the seat enforcement is removed.
Related features
- Unlimited-seat licenses: Opt out of seat enforcement on a per-license basis - shared keys with no exclusive HWID binding.
- Blacklists & whitelists: Block or allow specific HWID strings (exact match).
- License API: Generate keys with
maxHwidSlots, reset bindings, and more. - SDK overview: Install the official SDK for your language. All of them compute the same HWID.
- HWID override: Bind licenses to external identities (for example Telegram user IDs) instead of machine IDs.