Having A Public Api But Only Allowing Access To Requests Sent From My Website
Solution 1:
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.
Solution 2:
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:
- Minified JavaScript
- A token (such as a CSRF token) received from the server, which you then hash or transform in some way in the web client code
- Including the current date somewhere in the computation
None of the above would stop a sufficiently motivated attacker.
Solution 3:
In my opinion most secure solution is oauth2
or if you want to more flexibility oauth
.
It allows to generate and terminate access tokens. You can count how many sources is taken by any token and make it invalid if someone is trying to download all your data.
Great tutorial:
Post a Comment for "Having A Public Api But Only Allowing Access To Requests Sent From My Website"