I have been searching on Google and SO for hours now but without finding the someone with the same challenge as I now face so here goes:
We have a database with which we put a lot of money and effort into maintaining. The data from the database is publicly available through an REST-API. We also have a public javascript web app that consumes this API and which we sell to some 30-40 customers. As the data in the API is quite valuable to us we want to try to secure it so that no one can scrape the content from it and make their own copy of our database. Nor do we want anyone building services using our API without our consent. At the same time, we need our web app at http://www.example.com/theApp, http://www.example2.com/theApp, http://www.example3.com/theApp etc to be able to access the API. There are no users involved. Everyone can go to http://www.example.com/theApp and get the full feature of the site. The API is also read only so we are not concerned by anyone trying to pollute our data.
The javascript web app is built with react.js with a node.js server. SSL will, of course, be used for all communication between servers and client.
Things that I think will NOT work:
Things that might work (or at least be part of the solution):
As this is quite a complicated thing we are trying to achieve, heck I am starting to believe it might be impossible, I would greatly appreciate if anyone has some advice about what to do. "Don't do it" is a perfectly good answer if good reasons are given. I am more of the conceptual solution here, but if anyone wants to be concrete on software we have a Linux environment with node.js, Nginx and PHP.
If you don't want to authenticate your users (you don't want them to log in), you have no way to tell who is consuming your API, or what requests come from which user. All the information needed to make an API request is already in the javascript client, anybody can make another client, or a valid request to the API, and you can't even tell if the request is from a new client or the same as in a previous request (somebody that wants to download your database could just distribute downloading across many client computers).
Daniel's answer is probably the closest you can get to your goal this way. If you issue tokens, those at least can be revoked. However, you would still have no way to stop an attacker from requesting a new one.
My thought after reading your question was that a javascript web application is probably not what you want. You are saying you have relatively few clients and you don't want login at all. Would that be an option to give them something like a desktop/mobile client? It could still be Javascript wrapped in some kind of a container, but for each client you could compile one with their own key included. An obvious risk is that they could still extract the key, but this way not anyone could have a client with a key, in fact, a leaked key would be associated with its rightful owner, and you could have contractual clauses to cover that scenario (prohibiting reverse engineering, etc). You could also monitor and control mass-downloads of your database and revoke offending keys, or implement additional security measures like restricting key access to certain client IP addresses if that's possible in your scenario.
This risk of course may or may not be acceptable in your case, just an idea. Obviously, it would be easy to get a key from a client, the point is not everybody would have a client to get a valid key from. A better way would probably be to just distribute keys separately as license files for the client, it's essentially the same, but without the concept of "hard-coded keys" (which I think they are not really in this case). It would make your life easier as you would not need to distribute a full client in case of a revoked key, only a new license file.
This is of course authentication, but in a way that could probably be more user-friendly in your case, as users would not need to do anything.
Another thought for that number of clients is client certificates. To any client that wants to consume your API, you would give a client certificate. Anyone could download your web app, but client certificates could be used to authenticate callers to the API. It's the same as keys above, but at a different level. It's more difficult (and possibly more expensive) to revoke and issue a new one, and you could still not prevent downloading your whole database, but again, you would have proof who did that, and could revoke their key and cover this in your client contracts.
Obfuscation is your only option in the scenario described. You want to make it very hard for an attacker to reverse engineer your web client.
If the client is required to make a complicated computation in order to make a successful API request, then an attacker has to reverse engineer that computation and replicate it in another application.
Some things that would help:
None of the above would stop a sufficiently motivated attacker.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With