Skip to main content
Migrate Already selling? Move your customers to Keylight without re-issuing a single key.
Keylight

Use case · Tauri

Licensing for cross-platform Tauri apps

Add license keys to your Tauri app across macOS, Windows, and Linux — signed keys your app verifies offline, with the JavaScript SDK or the first-party Rust plugin.

Start Free

For indie developers shipping cross-platform desktop apps built with Tauri.

  • You ship the same app to macOS, Windows, and Linux and want one license layer for all three.
  • Rolling your own keys means crypto, a server, and a dashboard to maintain.
  • Desktop users expect the app to keep working offline.

Updated June 2026

Tauri is compelling for exactly the reason its adoption has grown quickly: you write a web frontend you already know, and you get a native desktop binary for macOS, Windows, and Linux without shipping three codebases. But when you go to license that app, the multi-platform story becomes a liability. You need a licensing layer that works the same way everywhere. This guide covers what that looks like and how to implement it without building infrastructure.

Why Tauri is an interesting licensing target

Most desktop licensing tooling was built for specific ecosystems. Native macOS tooling assumes Swift and the Keychain. Windows tooling assumes Win32 or .NET. When you ship a Tauri app, you are none of those things cleanly — you are Rust and WebView2 and a JavaScript frontend, running on three operating systems with different filesystem conventions and different secure storage behaviors.

The result is that most licensing solutions either target the webview (and give up tamper resistance) or target one native platform and leave the others unsupported. Developers end up with incomplete implementations: a key entry UI that only validates against a live server, a hardcoded free mode for platforms the licensing library doesn’t support, or a plain string comparison that any user can bypass with a hex editor.

Tauri’s architecture actually provides a clean answer to this. The app core is Rust. The frontend is arbitrary web technology. Commands bridge the two. A licensing layer built with Tauri in mind can put the verification where it belongs — in the Rust core — and surface the result to the frontend through Tauri’s command system, the same way any other native operation works.

What licensing a Tauri app requires

Cross-platform desktop licensing has the same fundamental requirements as any other desktop licensing — the challenge is meeting them uniformly across operating systems.

Signed keys. A license key needs to be unforgeable. That means cryptographic signing: the key encodes an entitlement payload (who purchased it, what product, what device limit, when it expires) and is signed with a private key your server holds. The app verifies the signature against a bundled public key. An unsigned key is just a string anyone can copy.

Offline verification. Desktop users launch apps without network access regularly — on planes, in corporate environments, in poor connectivity. A licensing check that requires a live server call has no good failure mode. Ed25519 signature verification is a local operation; the app can verify a signed lease instantly with only the bundled public key.

Platform-neutral storage. The license needs to persist across sessions. On each platform, the safe location differs. Your implementation needs to handle this without shipping three storage backends — or you end up with a race between platform detection bugs and user support tickets.

Revocation. When a refund lands or a chargeback comes in, the key needs to be marked revoked. The next time the app connects and revalidates, the server returns a rejection and the app gates accordingly. The license payload itself does not encode revocation — revocation is a server-side state that the app learns about through periodic online checks.

A dashboard. Customers lose keys. They get new machines. They need to deactivate an old device. Without an admin surface to look up licenses and reset activations, every request becomes a manual email.

Offline-first on the desktop

The constraint that trips up most DIY implementations is the same one that trips up web developers when they first ship a desktop app: the network is not always there, and that is fine and expected.

Tauri apps run everywhere a binary can run. That includes air-gapped machines, enterprise environments that block arbitrary outbound connections, and laptops that haven’t been online in three days. A licensing check that fails closed when it can’t reach a server will generate legitimate user-facing errors for customers who purchased correctly and are doing nothing wrong.

Offline license validation solves this by separating the two jobs: the signature check (local, instant, always works) and the revalidation (online, periodic, picks up revocations and entitlement changes). The app verifies the signed lease at launch with the bundled public key. If the lease is still within its validity window, the app unlocks. If a revalidation is due, it happens in the background after launch, transparently. The customer never sees a network-dependent startup.

This also makes your app more resilient as a developer. If your licensing server has an outage, your customers are unaffected until their leases expire — which you can set to days or weeks. The operational blast radius of a backend incident shrinks dramatically.

Integrating with Keylight

The JavaScript SDK runs in your Tauri webview:

import { Keylight, fetchKeyset, FetchTransport } from "@keylight-dev/js";

const ks = await fetchKeyset(new FetchTransport(), "https://api.keylight.dev", "your-tenant");

const kl = new Keylight({
  tenantId: "your-tenant",
  productId: "your-product",
  sdkKey: "<your SDK key>",
  trustedKeys: ks?.keys ?? {}, // enables offline lease verification
});
await kl.load();

const res = await kl.activate("USER-LICENSE-KEY");
if (kl.hasEntitlement("pro")) {
  // unlock pro features
}

For a more tamper-resistant check, verify in the Rust core with the first-party plugin:

cargo add tauri-plugin-keylight     # Rust side
npm add tauri-plugin-keylight-api   # JavaScript side

The Rust plugin registers a Tauri plugin that your frontend calls through Tauri’s command bridge. Activation and validation run in the Rust process, not in the webview, which means the check is not visible to browser DevTools and cannot be intercepted by proxying the webview’s network traffic. The result propagates to the frontend as a typed response through the same command system you use for any other native operation.

Both paths — webview JS SDK and Rust plugin — verify Ed25519 signatures locally. The trustedKeys parameter in the JS SDK and the plugin’s equivalent configuration ship the tenant’s public key to the client so the offline check works from first launch, before the app has ever connected.

When a customer purchases through Stripe, Keylight receives the webhook, mints a signed lease, and emails the key. The app never needs its own webhook handler. The dashboard gives you license lookup, activation reset, and revocation controls for support requests.

Getting started

Setup takes under an hour. Create a Keylight account, connect your Stripe account, and choose which integration path fits your app:

  • Webview path: install @keylight-dev/js, call fetchKeyset at startup to cache the public keyset locally, then activate() on key entry. Works in any Tauri app without touching the Rust side.
  • Rust plugin path: add tauri-plugin-keylight to your Cargo dependencies and tauri-plugin-keylight-api to your frontend. Register the plugin in your Tauri builder. The license state is owned by the Rust core and exposed to the frontend through commands.

Many apps start with the webview SDK to get something working quickly, then move critical checks to the Rust plugin before shipping. The two are not mutually exclusive — you can verify in the core and drive UI from the same trusted state.

Keylight plans start at $19/month on the pricing page. The free tier supports up to five licenses, which is enough to run the full activation and offline verification flow end to end before you ship.

The cross-platform problem in Tauri licensing is real, but it is mostly solved by picking the right layer for the check. Put verification in the Rust core, keep the UI informed through commands, and the platform differences stop mattering.

Frequently asked

Can I license a Tauri app?+

Yes. Keylight issues signed Ed25519 keys your Tauri app verifies offline — use the JavaScript SDK in the webview, or the first-party Rust plugin in the app core.

Should I verify in the webview or the Rust core?+

Both work. Verifying in the Rust core via the Tauri plugin is harder to tamper with than JavaScript in the webview, so many apps gate in the core and reflect the result in the UI.

Start licensing your app today

Drop in the Swift SDK, point it at your dashboard, and sell paid apps in under a minute. Free forever tier included.

Start Free