Developer Guide: Integrating Desktop Application Licensing
This guide explains how to use the Zero Token License Server to create, distribute, and validate licenses for a desktop application. The system relies on a secure offline validation model using asymmetric ECDSA (P-256) keys, eliminating the need for constant network connectivity after initial activation.
1. Setup in the Dashboard
Before distributing your application, you must define the product and generate activation codes for your users.
Registering a Product
- Log in to the License Server Dashboard (
license-server-dash). - Navigate to the Products section and create a new Product.
- This creates a unique
productIdfor your desktop application.
Generating Activation Codes
- Navigate to the Activation Codes section.
- Generate an activation code linked to your newly created Product.
- Distribute this Activation Code to your end-user (e.g., via email after a purchase). Note: Activation codes currently enforce a quantity and max machine limit of 1 per code.
2. Desktop Client Integration: Machine Binding
When the user launches your desktop application for the first time, it should prompt them for their Activation Code. The application must then bind the machine to this code to generate a license.
Capturing the Machine Fingerprint
Your application needs to collect hardware identifiers to create a unique machine fingerprint. The system uses the MachineFingerprintV2 format, which requires:
macAddresses: An array of strings representing the machine’s MAC addresses. (These are tracked but excluded from core hardware hash generation to maintain stable offline keys).- Additional hardware metrics depending on your client SDK implementation.
Calling the Bind API
Make an API request to the License Server to bind the machine and receive the license manifest.
Endpoint: POST /api/v3/licenses/bind
Payload:
{
"activationCode": "YOUR-ACTIVATION-CODE-HERE",
"machineFingerprint": {
"macAddresses": ["00:1B:44:11:3A:B7"],
"hostname": "user-pc",
"os": "windows"
}
}
The Server Response
Behind the scenes, the server:
- Validates the activation code.
- Extracts the
productId. - Delegates payload generation to the
dll-generator-worker(which generates.dll,.so, or.dylibdepending on the OS platform). - Signs the license manifest with the Server’s Global ECDSA Private Key.
The response will contain the licenseFile—a base64-encoded representation of the license manifest (which also encapsulates the server’s ECDSA public key for offline verification).
Save this payload to disk (e.g., license.json or manifest.dll).
3. Desktop Client Integration: Offline Validation
Once the license is saved to the local machine, your application can perform offline verification on subsequent launches.
Fetching the Server Public Key (Optional/Initial)
For completely offline verification, the client can use the embedded public key within the license payload. However, clients can also fetch the global ECDSA public key explicitly:
Endpoint: GET /api/v3/license/public-key
Requirement: The request strictly requires an Accept header containing either application/json or text/plain.
Verifying the License Locally
Your desktop SDK must:
- Load the
licenseFile(the base64 payload from disk). - Use the Web Crypto API (or equivalent native crypto library like OpenSSL/BoringSSL) to extract the manifest JSON and the signature.
- Verify the ECDSA (P-256, SHA-256) signature against the manifest using the provided public key.
- Verify that the
productIdin the manifest matches the expected product ID of your application. - Generate the current machine fingerprint and verify it matches the fingerprint stored in the manifest (ignoring MAC addresses).
If the signature and fingerprint match, the application is fully licensed and can launch normally.
4. Periodic Online Validation (Optional)
If you require periodic check-ins or want to update the license state (e.g., for subscription renewals), your desktop client can re-validate with the server.
Endpoint: POST /api/v3/licenses/validate
Headers:
X-License-File: The base64-encoded license file previously saved to disk.
Payload:
{
"machineFingerprint": {
"macAddresses": ["00:1B:44:11:3A:B7"]
// ... other fingerprint data
}
}
The server will return an updated license object, including a potentially regenerated licenseFile base64 manifest that your application should map and save back to disk, replacing the old file.