Ask HN: Safe? API Keys in Your JavaScript Client.
When building Single Page Apps with whatever-flavour-of-the-moment JavaScript framework, how do you go about securing access to API keys for your application?
This is separate to user authentication. I'm talking about allowing application A and only application A to access your REST web services.
Traditionally I've used an API key in server side apps, but in a client-side app, that API key is there for all to see and abuse.
This must be a common problem. How have other companies dealt with this problem? More to the point, when all of the REST requests require authentication, is it even a problem?
16 comments
[ 3.2 ms ] story [ 49.4 ms ] threadSee http://craphound.com/msftdrm.txt:
> In DRM, the attacker is also the recipient. It's not Alice and Bob and Carol, it's just Alice and Bob.
What applies to DRM applies to your webapp as well.
The best you can do is make this inconvenient: lock it down by IP range if you can. Make the javascript hard to reverse engineer (there are encryption tools out there). Have the API ask a question only a user would know. Password protect access to the app before you ever send javascript which accesses your web service. Do all this over SSL.
CAPTCHA-ish 'human authentication' for API requests would make things hard.
Moxie Marlinspike's older post on the cryptographic doom principle, at http://www.thoughtcrime.org/blog/the-cryptographic-doom-prin... also covers some of the basics.
You're much, much better off getting expert advice on this from folks familiar with your SPA/JS Framework.
The only way to get around it is if you dynamically generate the single page app API key, this somewhat negates the benefit of even doing a single page app (e.g. being able to store the entire "site" on a CDN or something like S3). Also being able to store it offline via Application Cache.
If you can generate the page you can have the generator script take the client's IP and an expiration time (e.g. +1 day), and then encrypt it using strong modern encryption (e.g. AES 256). The encrypted string is the "API key." The single page app then sends it to your REST service which decrypts it using the same encryption key, and checks the IP address against the requester, and the time against the expiration time.
If someone wanted to abuse your REST API they would have to route API requests through their own servers, which would then have to make a request for your single page app, extract the encrypted key, and then make the endpoint REST API request on the client's behalf. This is however easy to detect, just by looking at the same IP(s) connecting over and over.
Plus counter-measures to abuse would be easy to implement and likely effect.
But ultimately this breaks the whole single page application concept completely, and when it is all said and done you may have well have just saved yourself the headache and keep the API key server side. If you're using a third party REST service then everything I said above is irrelevant.
PS - This comment has so many caveats that it is barely useful.
The server-side component takes requests from the client, provides some authorization and rate limiting, and passes through the request to the remote API with the secret key being stored server-side.
For authenticating requests we typically check the Referer header (spoofable) and a rate limiter that aims to prevent automated queries but allow manual/regular use of the app (eg. allow 1 request per 1000ms).
Where the application logic exists client-side it will never be possible to completely encrypt anything, only temporarily obfuscate. Eventually you're forced to send a request to the remote server from an arbitrary IP that can be captured and replayed.
If it's your own API, and it requires authentication, then what behavior are you trying to prevent? If it's scraping, rate limiting is your friend. If it's unauthorized client creation, header checks will help (but are all spoofable). Keeping a good audit trail of requests will help to identify and close holes when they appear.
I'm interested primarily in mobile and web client accessing my own REST API. Users have to be logged in to do anything anyway but it doesn't stop someone who has a valid login from writing another application and abusing the system.
Like you said, you just need to be vigilant.