HTML5 offline authentication

authentication, encryption, html, javascript, security

Solution

Authentication vs. secure storage

I'll start with the big design issue: You seem to work with the problem as if it is about authentication, where the (potentially malign) user needs to prove to your application that she really is valid user. But actually you are facing a storage problem, because the whole runtime environment, containing all the sensitive information your application is working with, is in the hand of the attacker if the computing device is stolen. In the case of a javascript application the analysis of the offline data and code is even more comfortable than in the case of some binary only code.

For example if I would want to attack your application I would first look into the session storage (cookies? Simply use the browser interface to look them up) and see if I can find the username and password there. If not I would follow the code that is used to decrypt the password in the local storage (probably using a javascript debugger). The way you have described your application it seems like the functions can decrypt it without a key supplied by the user. Maybe I can just comment out the local authentication of the user by changing something like `if(authenticateUser())` to `if(true)`.

So what you really have to do is encrypt all sensitive, local data with a key that is not stored on the client side at all. For example ask the user for a decryption key every time he accesses your application, use that key to decrypt the locally stored data (and encrypt every new data you store) and throw the key away after a certain time of inactivity. Or you can authenticate the user against the server every time he accesses your application and retrieve the decryption key from there and throw it away after a certain time of inactivity.

At this point the choice of a javascript environment really hampers your cause as you cannot force the runtime environment to throw away the decryption key when you want it gone. It is difficult enough with C applications even, as you have to carefully work around swapping the RAM out onto the HDD. Depending on how sensitive the information your application works with is it might be enough to ask the user to close the browser after she is finished and assume that an attacker is not motivated enough to look for the key in swapped out RAM of the browser.

Locally saving the login data

As it is the most sensitive information you work with you should never store the user login information on the client. Instead authenticate against the server once and retrieve an authentication token from it for future interactions. This would be basically identical to a session cookie and expires after some time (if it does not expire at all it is as good as the password).

Problem

I am looking for advice/criticism on how best to control access to an HTML5 application that is used predominantly offline. The application uses a combination of IndexedDB, local and session storage to store data so that it can be used offline. The data/pages are served via HTTPS. The aim is to minimise the risk of the data being viewed if the tablet/PC was lost/stolen. Currently the application uses the Stanford Javascript Crypto library to encrypt the user/password and then save it to local storage if the user is able to successfully authenticate to the server. If the application then goes offline a user must authenticate 'locally' against the encrypted user/password in local storage. In addition an unencrypted user/password is stored in the session storage if the user is able to successfully authenticate to the server. This is used so that the application can periodically attempt to re-establish contact with the server and 'seemlessly' re-authenticate without requiring the user to re-enter their credentials. I am aware of a number of posts/discussions about the fallibility of client side encryption refer http://www.matasano.com/articles/javascript-cryptography/ and http://rdist.root.org/2010/11/29/final-post-on-javascript-crypto/ and .nczonline.net/blog/2010/04/13/towards-more-secure-client-side-data-storage/ + others. However I am unsure how these arguments apply in this scenario. I am looking for criticism of the approach given the need of storing data offline. If there is a better approach please elaborate. Thanks

Original source