Why a licence key is not a secret
· 4 min read
Customers ask us a reasonable question: if the licence key ends up in the JavaScript bundle, can't anyone copy it?
Yes. And it does not matter as much as it sounds like it should. The confusion comes from the word key, which in most contexts means "a secret you must protect". A licence key is not that. It is a signed claim — closer to a train ticket than to a password.
What is actually inside one
Ours is a base64url payload with an ECDSA P-256 signature over it. The payload is signed, not encrypted. Anyone can decode and read it, by design:
{
"lid": "KL-XXXX-2026",
"domains": ["example.com"],
"features": ["datagrid-editing", "pivot-charts"],
"exp": 1788000000
}
The signature does one job: it proves we issued that payload and nobody has edited it since. Change a single character — add a feature, push the expiry out — and verification fails, because the forger does not have our private key.
Verification is offline. The public key is compiled into the package, so the grid checks the signature locally and never calls home. No licence server, no runtime dependency on us, no telemetry. Your app keeps working if our site is down, and it keeps working on an air-gapped network.
That property is worth more to customers than any anti-copying measure would be.
What the key can and cannot do
It can prove the payload is authentic, bind the licence to specific hostnames, gate specific features, and expire.
It cannot stop a determined person from using your library without paying. Nothing shipped to a browser can. The code is on their machine; the verification runs on their machine; a sufficiently motivated developer edits the check out. This is not a flaw in our design, it is the nature of client-side software. Every library in this category is in the same position, whatever their marketing implies.
So the honest framing is: licensing is a billing mechanism, not a security
boundary. It exists so that companies who want to comply can comply — cleanly,
verifiably, without a phone-home dependency. Companies that want to steal
software were never going to be stopped by an if statement.
Once you accept that, several design decisions get easier.
Design consequences
Domain locking is the useful control. A key bound to example.com is
worthless to someone who copies it onto their own site. That is a much stronger
practical protection than secrecy, and it degrades gracefully: the worst case is
a wrong domain, which shows a watermark rather than breaking the app.
Failure has to be soft. If a key is missing, expired or wrong, the grid still renders and still works — it draws a watermark. Hard-failing a UI component over a billing state means a customer's production dashboard goes blank because a renewal email went to a spam folder. No licence check is worth that.
Local development must not need a key. Ours skips the domain check entirely
on development hosts. Requiring a key on localhost mostly punishes the
evaluating developer — the exact person you want to have a frictionless first
hour.
Then why does our own site ship a key?
Because our demos use the paid features, and we would rather not show visitors a watermark on every playground page. So the site carries a key, and it is visible in the bundle. Deliberately.
We made it narrow on purpose: it is bound to our own hostnames, it carries only the features the demos actually need, and it is short-lived. If someone lifts it and puts it on their own site, the domain check rejects it and they get the same watermark they would have had anyway.
The one real cost is worth stating plainly. Because development hosts skip the
domain check, a copied key does work on someone's localhost. That is an
accepted trade: it lets people evaluate the library comfortably, which is what
we want anyway, and it converts to nothing the moment they deploy.
What this means if you are choosing a component library
Two questions worth asking any vendor:
- Does verification happen offline? A licence check that calls a server is a runtime dependency on that vendor's uptime, forever, in your production app.
- What happens when the licence is invalid? If the answer is "the component throws", you have coupled your application's availability to your billing status.
Neither question is about how well the key is hidden. That was never the part that mattered.
Ours is described in Enterprise & licensing. One key covers both components.