I have a JavaScript application.
It's built with jQuery.
It uses $.get()
to pull JSON data from a server, and uses the data to load a puzzle.
I want to distribute the JavaScript application to clients, and make it easy for them to install.
I'd like it to simply give them a JavaScript block they can drop into their page, and it will interact with my API.
I'm not passing sensitive data, any my API is protecting the database from SQL injection, etc.
I just want to try to prevent unauthorized use of my API, and I can't think of a way to do that with JavaScript, since anyone with a DOM inspector can scrape any credentials from any variables or can monitor any server traffic POST or GET data...
Would it be possible to authenticate the referrer on the other side?
I know that's not bulletproof, but it's not sensitive data. I just want to reduce the unauthorized use as much as possible..
Any ideas?
note: I know obfuscating an API key or something is futile, I'm wondering what other controls I could put in place other than a traditional key to identify the caller to the API.. I have full control over the API itself so I could do anything on that side of things...
JavaScript authentication has holes
With JavaScript, just about any authentication system is going to have holes, simply because the code runs directly in the browser and can be seen by anyone (as can the network calls). So there are a couple of things you can try, depending on your situation.
IP whitelisting
If you are distributing this application to a small subset of clients, and you know exactly where they will be accessing it from, you could use IP whitelisting. This really is the only way to completely secure the API. However this method is very cumbersome, since with every new client you have to update the API whitelist, and considering what you're talking about here probably not what you're looking for (but I mention it just because it is a possibility).
Access tokens
Another method is access tokens. This is a common method used by sites such as Facebook. There are two methods to do this. One is to just give each client a secret key. You can have the same secret key for everyone, but this is not very secure. Having a different secret key for everyone allows you to not only track usage, but also revoke access privs if necessary.
The first method for access tokens is to just give it inside the JS client. However this means that anyone who looks at the source will be able to access your key, and make requests using it.
The second method is to have the secret key stored somewhere on the SERVER of the website where your client runs. This server can then make a server-to-server call using that key to obtain a temporary session token. People will still be able to access the temporary session token via the front-end, but they will have to access this site first in order to get it (this allows you to pass off responsibility for handling this to the website operator) and the token will eventually expire. However this means there needs to be some server-side code, and the app won't just be a drag and drop thing.
For the method given above you can also look into things like OAuth, to avoid re-inventing the wheel.
Whitelist hard-cap
Another possible thing using IPs is to set a hard-cap on either how often or how much per day a specific IP can hit the whitelist. Though you may run into problems with users who REALLY like the puzzles, this will prevent some of the potential abuse.