Skip to Content
macOS (Swift)Machine fingerprint

Machine fingerprint on macOS

The SDK computes the fingerprint it sends with each validation, and checks in each token. Each fingerprint LicenseManager hasn’t seen on a license is a new machine, which takes one of its places.

await licenseManager.fingerprint() // "q3M0bVZ0…Hk=:Xk9fT2pB…w=:x7Kp2QaZ"

What it’s made of

Three parts, joined with ::

PartWhat it isTies the fingerprint to
MachineThe SHA-256 of the system’s machine id, in base64.The computer.
Install id32 random bytes, in base64, generated the first time and stored in the keychain.This installation.
Product idYour product id.Your product.
  • The machine part makes the fingerprint stable, and different on each computer. It’s hashed, so the raw id is never sent.
  • The install id makes it hard to fake: copying the machine id of another computer isn’t enough, the secret stored on it is needed too. Copying your app’s files to another computer doesn’t copy it.
  • The product id makes the fingerprint different for each of your products on the same computer.

The fingerprint is computed the first time it’s needed, then kept in memory while the app runs. It’s about 100 characters long, within LicenseManager’s limit of 255.

It’s computed exactly like the Electron SDK’s and the Tauri SDK’s: the same Mac gets the same fingerprint with all three. See migrating from Electron or Tauri.

The machine id

The Mac’s hardware UUID, IOPlatformUUID, the one System Information shows as Hardware UUID. The SDK reads it with IOKit, the same value ioreg -rd1 -c IOPlatformExpertDevice prints, without running any command: it works in the App Sandbox. It stays the same when macOS is reinstalled. The value is lower-cased, and spaces are removed.

When it can’t be read, the SDK falls back on the MAC address of the first network interface that’s up and isn’t the loopback, then on the hostname. Both are less stable: a MAC address can change with a new network adapter or a dock, and a hostname when the computer is renamed. Reading the machine id never fails.

Reinstalls and updates

EventSame fingerprint?
Restarting the app or the computerYes.
Updating your appYes.
Updating macOSYes.
Uninstalling and reinstalling your appYes: the install id is stored outside your app’s folder, and survives it.
Moving from an Electron or Tauri build of your app to a Swift buildYes.
Reinstalling macOS, with the Keychain restoredYes.
Deleting the stored dataNo: a new install id is generated.
Moving to a new computerNo.
Another user account on the same MacNo: the stored data is per user, so each user gets their own install id.

A new fingerprint is a new machine. The old one keeps its place until it’s deactivated, by you, or by the customer from the customer portal.

Overriding the machine id

Pass fingerprint to choose the machine part yourself, like to license per user instead of per computer. It replaces the machine id only: the result is still hashed, and combined with the install id and product id.

// A fixed value: LicenseManager.Options(fingerprint: .value(currentUserID())) // A function, sync or async: LicenseManager.Options(fingerprint: .provider { await readMyDeviceID() })
  • A function is called the first time the fingerprint is needed, and its result is kept while the app runs.
  • It returns a String, and can’t throw: return a fallback value yourself when your source is unavailable, and keep it stable.
  • An empty string is accepted: every computer then has the same machine part, and only the install id tells them apart.

See choosing what a machine is for what to use.

Don’t change the fingerprint once you’ve shipped, by adding, removing or changing the fingerprint option. Every computer becomes a new machine at its next validation, and licenses with a max machines start refusing them with machine_limit_reached, until the old machines are deactivated. Their stored tokens stop working offline too. When migrating from Electron, keep the same fingerprint option you had there.

Edge cases

Cloned virtual machines share the same machine id. A clone of a virtual machine where your app was already activated also copies the stored install id: both have the same fingerprint, and share one place. Clones made before the first launch of your app each generate their own install id.

CI runners, which are often fresh virtual machines: each run can be a new machine. Use a test product, or pass fingerprint.

The keychain can’t be written and the file fallback fails too, like on a read-only home folder. The install id can’t be stored: a new one is generated on each launch, and each launch is a new machine. It’s very unlikely on a customer’s computer.

Two products on the same computer have two different fingerprints, and are two machines, one in each license.