How Offline License Validation Works
“Offline license validation” sounds like a contradiction — how can an app confirm a customer paid if it cannot reach a server? The answer is one of the more elegant ideas in software licensing, and once it clicks, online-only validation looks like the strange choice. Here is how it works.
The mental shift: trust math, not a server
There are two ways an app can answer “is this license valid?”
The first is to ask a server. The app sends the license somewhere, a database is consulted, and an answer comes back. The answer is always current, but the app is helpless when the server is unreachable.
The second is for the app to work it out itself. This is possible when the license is not an opaque code that only a database can interpret, but a signed document that carries its own proof of authenticity.
That is the whole shift. Offline validation means the app trusts mathematics it can run locally, instead of trusting an answer it has to fetch.
The cryptography, briefly
Offline validation rests on public-key signatures. There is a key pair:
- A private key lives only on the licensing server. It is used to sign.
- A public key is embedded in your app. It is used to verify.
When a customer pays, the server builds the license — who it is for, what it covers, when it expires, how many devices — and signs that data with the private key. The signed result is the license.
Your app ships with the public key. To validate, it runs the signature-verification function over the license data and the signature. The function returns true or false. True means: this license was signed by the real private key and has not been altered since. That check is pure computation. No socket, no latency, no server.
The security holds because the public key cannot be used to create signatures, only to check them. You can ship it to the entire world. An attacker who has your app, your public key, and a valid license still cannot mint a second valid license or edit the one they have — any change breaks the signature.
Why desktop apps need this
For a web app, offline validation is pointless — the app is always online by definition. For a desktop app, it is close to essential.
A Mac or Windows app launches on a plane, in a hotel with a broken captive portal, on a train through a tunnel, behind a corporate firewall that blocks unfamiliar traffic, or simply when the home internet is down. In every one of those moments, an online-only license check cannot reach its server. The app is then stuck with a bad choice: refuse to run — and lock out a customer who paid — or run anyway, in which case the check confirmed nothing and can be bypassed by anyone who blocks the network. The deeper problem is that the app has no way to verify the license itself.
Offline validation removes that entire class of failure. The check is local, so it succeeds in milliseconds regardless of the network. A deeper treatment of the model lives in the offline license validation guide.
The honest catch: revocation
If the app never asks the server, how does a refunded customer’s license ever stop working? This is the real tradeoff, and it is worth being direct about it.
Offline-first does not mean offline-only. A good system pairs local validation with periodic online revalidation. Every launch, the app validates the signature locally — fast, always works. Separately, every few days, when a connection is available, it makes one background re-check. That re-check picks up anything the local check cannot see: a revocation after a refund, a chargeback, an entitlement change.
So revocation is not instantaneous. A refunded customer who stays offline keeps a working app until their next online re-check. In practice almost everyone reconnects within hours, so revocation lands within days. That is a good trade: every honest customer gets an app that always launches, and the cost is that dishonest ones lock out a few hours later than they theoretically could.
What it looks like in an app
With a licensing SDK, all of this is one call. checkOnLaunch() verifies the cached signed license locally first — instant, offline — then schedules a background revalidation if one is due:
import KeylightSDK
await licensing.checkOnLaunch()
switch licensing.state {
case .licensed:
enablePaidFeatures()
case .trial(let daysLeft):
showTrialBanner(daysLeft: daysLeft)
case .expired:
showRenewalPrompt()
case .invalid:
showActivationSheet()
}
The customer never waits on the network to launch. The server is consulted only occasionally, in the background, and an outage on your side never locks anyone out.
Offline validation is not a compromise — for desktop software it is the correct default. Online-only validation trades every honest customer’s reliability for slightly faster revocation, and that is a bad trade. If you would like more depth on any part of this, send us your feedback.
Frequently asked
How does an app validate a license without internet?+
The license is cryptographically signed. The app ships with a public key and verifies the signature locally in memory. If the signature and entitlement fields are valid, the license is accepted — no network call.
If validation is offline, how is a refunded license caught?+
The app revalidates online periodically, typically every few days. A license revoked after a refund is rejected on the next online re-check — not instantly, which is the deliberate tradeoff for offline support.
Is offline validation less secure than online validation?+
No. A signed license cannot be forged without the private key, so offline verification is cryptographically strong. The only difference is revocation latency, which periodic revalidation handles.
Ready to ship?
Create your account and start licensing your apps in under a minute. Free forever tier included.
Start Free