Skip to Content
ElectronClock tampering

Clock tampering

Offline, the only way to know a token has expired is the system clock. A customer could set their clock back to keep using an expired token, or one of a license you expired. The SDK detects it, and refuses to fall back on the stored token while the clock can’t be trusted: the state becomes CLOCK_TAMPERED.

license.isClockTampered(); // false

How it’s checked

The check runs when the LicenseManager is created, then every hour. It never throws, and never blocks your app.

With network time

The SDK reads the current time from the Date header of https://google.com, with a HEAD request and a 5 second timeout. When it gets an answer:

  • the clock is tampered when the system clock is more than 5 minutes off from that time, ahead or behind,
  • otherwise, it isn’t, even if it was at a previous check,
  • the network time is stored as the latest time seen.

Without network time

When the request fails, the SDK compares the system clock with the latest time seen, stored by the previous checks:

  • the clock is tampered when it’s earlier than the latest time seen, by any amount,
  • otherwise, the system clock becomes the latest time seen.

Offline, a clock found tampered stays tampered until a check with network time finds it correct, or the app restarts with a correct clock.

The latest time seen is stored with the license, so it survives restarts: setting the clock back, then restarting the app offline, is detected too.

What it changes

Only the offline fallback looks at it. When LicenseManager answers, the answer decides, whatever the clock:

LicenseManagerClock tamperedState
Answers with a valid tokenEitherACTIVE
Answers with a locking errorEitherThe matching locked state.
Can’t be reachedNoACTIVE on the stored token, or OFFLINE_EXPIRED.
Can’t be reachedYesCLOCK_TAMPERED, even with a valid stored token.

In CLOCK_TAMPERED, the SDK retries with a backoff, and becomes ACTIVE as soon as a validation succeeds. The stored token is kept.

isClockTampered() returns the result of the latest check, at any time. You don’t need it to lock your app, the state already does, but you can use it to explain the problem, like in a support screen.

What to tell the customer

“Your computer’s date and time look wrong. Turn on Set date and time automatically in your system settings, then connect to the internet.”

Edge cases

A clock that’s simply wrong, like on a computer whose battery died, or without automatic time. More than 5 minutes off, it counts as tampered: the app works online, but can’t fall back on its token offline. With network time available, it’s no longer tampered as soon as the clock is fixed, at the next check.

A clock far behind or ahead, online. Tokens are checked against the system clock: more than 2 hours behind, a fresh token isn’t valid yet; ahead by more than the token’s lifetime, it’s already expired. The validation gets an invalid_response, falls back offline, and the clock check finds the clock off: CLOCK_TAMPERED. During activation, setLicenseKey() throws invalid_response.

A clock 10 minutes off, online. The validation succeeds, and the app is ACTIVE, but isClockTampered() is true. If the customer goes offline later, the next fallback gives CLOCK_TAMPERED.

google.com is blocked, like on some corporate networks or in some countries, while LicenseManager can be reached. The check runs without network time, comparing with the latest time seen. Nothing changes as long as validations succeed.

Time zones and daylight saving time don’t change anything: the check compares absolute times, not the time shown to the customer.

A small correction of the clock offline, like by a few seconds, right after a check. It’s detected as tampering when it goes back before the latest time seen: there’s no tolerance without network time. It’s rare, since the latest time seen is only updated every hour, and it clears at the next check with network time.

The clock check is a deterrent, not a guarantee: someone with full control of the computer can also fake the network time. It stops the common trick, setting the clock back, without bothering honest customers.