This Q&A is part of a weekly series of posts highlighting common questions encountered by technophiles and answered by users at Stack Exchange, a free, community-powered network of 100+ Q&A sites.
Jesus Rodriguez asks:
My question has to do with JavaScript security.
Imagine an auth system where you’re using a JavaScript framework like Backbone or AngularJS, and you need secure endpoints. That’s not a problem, as the server always has the last word and will check if you’re authorized to do what you want.
But what if you need a little security without involving the server? Is that possible?
For example, say you’ve got a client-side routing system and you want a concrete route to be protected for logged-in users. So you ping the server asking if you’re allowed to visit protected routes and you go on. The problem is that when you ping the server, you store the response in a variable, so the next time you go to a private route, it will check that if you’re already logged in (no ping to the server), and depending on the response it will go or not.
How easy is for a user to modify that variable and get access?
My security (and JavaScript) knowledge isn’t great. But if a variable is not in global scope and is in the private part of a module pattern which only have getters but not setters, even in that case, can you hack the thing out?
See the original question here.
Sending secret data
Joachim Sauer answers (66 votes):
It’s simple: any security mechanism that relies on the client to do only what you tell it to do can be compromised when an attacker has control over the client.
You can have security checks on the client, but only to effectively act as a “cache” (to avoid making an expensive round-trip to the server if the client already knows that the answer will be “no”).
If you want to keep information from a set of users, make sure that those users’ client never gets to that information. If you send that “secret data” together with instructions “but please don’t display it,” it’ll become trivial to disable the code that checks that request.
As you see, this answer doesn’t really mention any JavaScript/Browser specifics. That’s because this concept is the same, no matter what your client is. It doesn’t really matter it’s a fat client (traditional client/server app), an old-school Web application, or a single-page-app with extensive client-side JavaScript.
Once your data leaves the server, you must assume that an attacker has full access to it.
Related: “What’s the best way to learn how to develop secure applications?”
Another route
Benjamin Gruenbaum answers (17 vote):
Please read Joachim’s answer before reading this one. He covers the general reasons behind client-side vulnerability. Now, for a suggestion how you might get around this problem:
A secure scheme for client-server communication without having to authenticate with the server manually on every request:
You’re still letting the server have the last say and the server still has to validate everything the client says, but it happens transparently.
Assume HTTPS protocol to prevent MITM (man in the middle) attacks.
Client handshakes with server for the first time, the server generates a public key for the client and keeps a private one in an asymmetric encryption scheme. Client stores the server’s “public” key in the local storage, encrypted with a secure password you don’t save anywhere.
The client is now offline. The client wants to perform trusted actions. The client enters his password and grabs the server’s public key.
The client now performs actions based on his knowledge of that data, and the client encrypts every action he performs with the server’s public key for that client.
When the client is online, client sends its client ID and all actions the client performed are sent to the server encrypted with the server’s public key.
Server decrypts the actions, and if they are in correct format it trusts that they originated in the client.
Full Story How easy is it to hack JavaScript in a browser? | Ars Technica.