Web Development – Best Approaches for License Key Solutions in Web Applications

licensingweb-applicationsweb-development

I am stumped by a request from my manager. I work for a small startup and we developed a web application for a fixed rate with a maintenance agreement for a MUCH larger company. Knowing horror stories about how large companies will only pay their bills to the last second we decided that we would like to protect ourselves by being able to license this web application in a way that if we don't get paid the software no longer works.

I have seen this done before for desktop applications however this will be a web application that they will host internally and will not be accessible from the Internet.

What is the best approach to do this, we would like it to have a small footprint and would like the ability to renew the license key that they have distributed.

Has anybody done something similar? Are we completely out of our minds? Does anybody have any better suggestions?

Best Answer

There are many ways to implement something like this, but here's one that shouldn't be too hard to do:

You need a publicly-available website somewhere that hosts a file containing the hashes of license keys that have been blacklisted. How you manage this file is up to you, but the file itself need only have a hash per line.

Then, on a recurring basis, your software initiates a download of this file (most server-side languages provide for this) and then searches it for the hash of the installed license key. If it is found, then the application knows that it should die until the blacklist is removed.

MD5 or similar plus a secret should be sufficient for this. You could get fancier and have the application send the request to your site and you look it up in a database on the fly, but the file (for what I'm assuming would hopefully be a short list) would hopefully remain small and may be the easiest way.

The harder part is going to be keeping the application dead. After all, you've got to store this somewhere internally, which means if it is overly obvious it could be easily subverted, and even if it isn't overly obvious, it can be easily reverted by restoring the appropriate table(s)/file(s). Therefore I suggest a second method of protection as well.

This method would store "LIVE" or "DEAD" (or something sufficiently similar) in a table or a file, but again HASHed. This needs to be hashed with your salt AND a timestamp. Everytime a page on your application runs, check this value with a hashed version of "LIVE"+salt+timestamp and then permit for a valid range of timestamps (for example, one day, two days, one week, one month, etc. Keep in mind the larger the range the harder performance will take a hit.). As long as things match (or a match is found), the app is alive; otherwise, even if the value in the special file or table is "LIVE", it will still be dead if there is attempt to restore from backup because the timestamp will fall outside your threshold.

In summary (this does assume that you have some programatic method of checking the validity of a license key, such as some sort of checksum or other method):

  • CheckBlacklist
    • Convert License Key to hash with salt
    • Request blacklist file from server
    • Is my hash in the file?
    • If YES, then store hash of "DEAD" + salt + timestamp (truncated to day; no need to store hours+days+minutes)
    • If NO, then store hash of "LIVE" + salt + timestamp (trunc'd)
  • IsKeyAlive
    • Create hash from "LIVE" + salt + trunc'd timestamp
    • Load DeadAlive hash
    • Do they agree?
    • If YES, then we're alive; return TRUE.
    • If NO, then we're possibly dead, but we may still be within our timestamp window:
      • Subtract a day from the timestamp and repeat hash.
      • Do we agree now?
      • YES? Return TRUE
      • Add a day to the timestamp and repeat hash
      • Do we agree now?
      • YES? Return TRUE
    • At this point, we're out of the timestamp range with no match. Return FALSE. (Kill app)

Now, goodness knows there's a million and one ways this can fail. Consider all the possible ways and build a reliable system (including one that assumes the client is right if the blacklist file can't be downloaded). Test, test, test it, and then test some more before deploying, because if it goes wrong, you'll have lost your client's trust.

Related Topic