User authentication in offline web apps - javascript

I'm building a web app that needs to work offline. The system is built to capture sales transactions. The bulk of the "offline" part is fairly straightforward -- I just need to store data locally and sync it when I'm back on the network. So far, so good.
The problem is with authentication. The app will run on a shared machine with a single OS user account. If I'm offline, how do I authenticate the user?
Users themselves do not have any private data that I will need to segregate (i.e., I don't have to protect them from each other on the client). I need to be able to validate their password so I can let different users login throughout the day even if the connection is down.
One approach I'm thinking of involves caching the password hashes on the client-side in an IndexedDB. Only a limited set of users will be allowed to log in from a specific shared machine, so I won't need to cache my whole password database locally. Assuming that I have a good password policy (complexity and expiry requirements) in place and the hashes themselves are secure (bcrypt), just how horrible of an idea is this?
Do I have any other options?

This is effectively how Windows (and other systems) work when the machine is not able to reach the domain controller (e.g., you take your work laptop onto the airplane and need to log into your laptop w/o connectivity). Your machine has written down a cache of your username|password pair and will let you in via those credentials even if it's offline.
I think generally speaking storing the username|password hashes is pretty safe, assuming you're hashing them reasonably (e.g., using a salt, using an IV, etc). One exposure you'll want to think through is having the hash file "escape." If this is sensitive data you'll want to be exceedingly careful -- and this may not even be acceptable, but if it's not super sensitive data then you're probably OK: with good hashing I think you should be reasonably (but certainly not completely) safe.

Maybe this is little unrelated, but I use this approach in my nodejs project.
When a user is authenticated by username and password, he/she is assigned a unique API key used only for this particular session.
Each user can have only one API key.
This API key is added to any request done to server, to authenticate the user.
When the user logs out, the API key is deleted. Also the API key can be purged on the server, that makes the user authenticate on the server one more time.
I can provide links to nodejs open source programs that use this approach if you interested.

Related

I want to limit the total number of articles read on my webpage by a user, without signup, like how medium does

I don't have any idea how to implement this. After a bit of search I found out that medium keeps track of the browser and not the user, what is mean is you can access three free articles from each new browser on the same machine (if I am wrong do point it out). I am using React and Firebase for my website.
Edit: I was thinking along the lines of getting some kind of id which is unique to a browser. As cookies and local storage can always be bypassed.
I don't know if it's a clean way to do it but you can associate an IP to an unique counter. Or with a cookie but he can bypass that by cleaning the cookies
The answer would tightly depend on your application setup and especially on the service backing your front store.
If you are using a self-backed backend, for example a nodejs - express based server, within your route middleware you can access the remote address from the req.connection.remoteAddress request property along with the user-agent req.header('User-Agent') and forward these to your datastore being Firebase in this case.
If you are deploying your application to Google Cloud Function, you can then access the remote peer address using the fastly-client-ip request header and still forward this to your storage system.
Use javascript and implement a system that uses a cookie or local-storage to verify how many articles are read on your website.
On most of these websites however you are still able to bypass this limit by clearing the cache or using a incognito window.
To also limit these scenarios you can use a cookie in combination with an IP address, which has its own drawbacks, especially in corporate environments, and mobile connections where IP addresses are heavily shared or changed. Depending on your situation this may matter or not.

How to securely store password in local storage

I realize that there are other posts on Stack Overflow asking similar questions, and the answer is to NOT to store passwords in local storage, but I need to. If there is a better approach, please let me know.
I am building a password manager. I am trying to develop it to work mostly offline. The way it works is that the user stores their "vault" on my golang web server. The server is only ever accessed when the client or server needs to be updated. So: the user logs in, the vault is sent from the webserver to the client, each time a password entry (username, password, name, etc) is created, each aspect of the entry is encrypted using the user's "master password". Since I would like the webapp to be able to work offline, I need to store some version of this master password in local storage or as a cookie (preferably as a cookie). I would like it to work similarly to other password managers, so if anyone can provide some insight on how they approach this problem, please do.
What is the best way for me to store the master password locally? I would like my approach to be as secure as possible. If there is a different approach I can take, I would love to know. My main thing is that I need the webapp to be able to work offline.
Please note that I am not using node. If I can provide any additional information, please ask.
Thank you!
The best way is to (as everyone is saying) NOT save data locally. That is a huge security issue. Other thing is that a Website can not be offline (unless its a PWA), so running the website offline is never gonna happen (Unless you create a PWA).
My Suggestion is that if you want to make it work offline you can create Chrome extension and use chrome.storage API for storing Encrypted password ( storing plain password is not recommended ). Even with web extension, it is not advisable to store password locally.
You can make it work offline if user is logged in and but not connected to internet anymore and browser is still running. Every time user open browser after closing it, you should (always) authenticate user again.
1). Since you are encrypting vault using plain master password, you can use any encryption/decryption method to encrypt master password ( which will be stored using api ) and to decrypt the stored encrypted password ( decryption is required as you will need plain master password for verification ).
Hashing algorithm is not a good option here, since hashing is one way encryption and depending on which algorithm you use you can have different hashes for same string.
2). Yes, you can check storage.local browser compatibility here
Electron can help you to develop what you want. With Electron you can develop offline app's to any S.O.
And you only need to know about HTML, JavaScript and CSS.
Take a look at official website
Today a lot of apps are made using Electron, like VS Code, Slack and a bunch more, look at this link: App in Electron
And if you really want to test, do a simple app following this Tutorial.
To store your password locally you can do a encrypted key and concatenate the machine info to make part of the password.
For example:
You can get programmatically machine MAC Address +
And do a simple and less secure MD5 encryption, and you will get something like this: e99cde2308fb2ff5612f801c76b18f6c
In the world exists a lot of encryption manners.
Good luck.

Secure way to store sensitive API details of users (localStorage or database?)

I am playing around with the idea of creating a website for cryptocurrencies, where a user can sign up on my website, enter his API details for one of the exchange markets that I will support, which allows him to trade on that exchange, but using my “more user friendly” web interface.
My main goal is to create a more user friendly interface than what most exchange websites offer. I am not hooking directly into any cryptocurrencies or wallets, all I do is use the API of existing exchange markets, relay the information to my website, where I have a more user friendly interface.
Since this is a very sensitive subject in regards to security, I am trying to figure out, what the best way would be to store the API details of the users.
In general I don’t like the idea of storing the API details on my database server, nor on my server in general. The thought of having my website hacked and all the API details being exposed is terrifying. Of course each exchange website that supports APIs has their own security built in, such as API sessions with 2FA, IP restrictions, weekly generations of new API secret keys, daily trading limits via API, and not allowing withdrawals of wallets via API. But damage can still be done if those API details get stolen.
I would prefer if there would be a way where I would not need to store the API details on my server at all, but rather have the user save them locally on his PC. That way he is in charge of keeping the API details secure.
This thought brought me then to the idea of creating a desktop app using electron (https://electron.atom.io/). That way I can still create the website the way I want, but it’s wrapped into electron, so it always run locally. Before I pursue this idea, I would like to keep investigating my previous idea of a regular website, as I prefer to have my website cloud based, SaaS, to prevent piracy.
So I wonder, storing API details of a user, without saving them on the server, what other options would I have?
Cookies? Probably not secure.
What about localStorage? https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API
Are there other options or am I too paranoid about this? Is it generally accepted to store sensitive API details on a database server along with the rest of the users details?
I think saving data in to users computers is wrong way, because when you will save user's personal data in to your server, you will be able to control security of your server, when it will be saved on user compputer the security of your server will be depended from users. Today we know many methods how to deceve users and I think, that the programmers must take care of his users. when you will save data in server db you can switch many methods, like email verification or verification by phone you can send message with some verification code, switch ssl service, also you can avoid on sql injection using a modern framework like Laravel or Yii 2, in any case if you will save user data in you server the security of your application will be depended of you.
if you will save user data in local computer, today hackers uses many methods to steal users cookies or methods to get a controll on pc, for example you can read this post
https://krebsonsecurity.com/2011/09/right-to-left-override-aids-email-attacks/
today hackers using this method, creates an exe file which extension on first look is docx or other some extension for example pdf and so on ...
but in real it is an exe file and it is runnable, user can download it, and run... I think you understood what can do hacker with users computers by this way, today so many viruses which even very professional users cant recognize.

Is it safe to store a sensitive data in Local Stoarge or session storage? Localstorage allows to any attacks for sensitive data

In web application , How secure is local storage in Html5 or else is there any other way to secure the sensitive data in local storage.
Project Structure:
Front End: Html5,Angular js, Middletier: Asp.net webApi , BackEnd :Sql Server.
Once user login into the page, that credentials is encrypted by using some cryptography algorithms.It will be stored in db.
After that every child action like products list, order details, book history ,add product need to validate that.
While refresh after the page, data gets lossed so need to persist the data so i have choose localstorage. stored the username and password encrypted using some js algorithms and in put in local storage.
I feel it as not safe , because of any one can steal the data from the browser tools.
Is there any alternative approach in this scenario or else this approach is secure.
can anyone help me to process.
There is something that every Webapp Craftsman must know:
There is no repository beyond your firewall that can be fully secure. Why? Because the open door that you NEED to allow your application manipulate the data is accessible to everyone.
Imagine that you decide to encrypt the content of the local storage.
This will prevent someone with access to the browser's local storage (e.g. the developer tool) to be able to read/write the data. But how your application will access the data? You have two options:
Send the encryption algorithm + passphrase within the client-side app. This will expose all your data if someone manage to read the code of your app and access to memory of the browser (e.g. the developer tool)
Send every data from the client-side to the server to be decrypted there. Well ... this is pointless. Is better to store the data in the server for that matter.
You can try as much as you want, you will need an open door, and that open door can be use by anyone.
But I've a question for you: Do you really need a fully secure repository in the client side? This kind of repository weren't created for be fully secure, but they are secure enough!
For example, the session cookie of your web app is stored by the browser right? And if someone steal that cookie, it can impersonate the user and your application will never notice it, right? This is pretty scary when you think about it.
Nowadays nobody put to much thinking on this because browsers are secure enough to protect cookies from malicious access. And of course, they did the same to protect the local local/session storage, IndexedDB, WebSQL, etc.
So, if your data is more precious than your user session, keep it in the server. If not, go ahead and put it in the browser.
PRO TIP: Consider encryption when storing in a no secure repository to make it harder to get. But remember that this comes at a price: you will not be able to use the query system of those repositories to search over encrypted data.

HTML5 offline authentication

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
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).
I have now implemented a solution which I describe below in case it is useful to someone else. I do understand it is 'not an answer' to my question i.e. does not offer critique, but given that the application must work 'offline' along with the requirement of seamlessly re-authenticating I cannot see how #Perseids answer can be implemented, although I do appreciate the dialogue (from both #SilverlightFox and #Perseids).
If there is a solution to not having to store the user's credentials 'offline' while fulfilling the requirements outlined in my question I would be keen to hear.
The application must be able to authenticate a user when the application is 'online' and 'offline'. For an 'online' application normally a session token solution would be adopted i.e. only a session identifier would be stored on the client (usually in a cookie) but not the user's credentials. However the user's credentials necessarily have to be stored on the client (perhaps someone will come up with a clever alternative?) so that security can be enforced while the application is offline i.e. allow a user to authenticate while offline and decrypt/encrypt IndexedDB data. In order to make the application more secure, the user's username and password are stored in an encrypted form. Some sensitive IndexedDB data is also stored in an encrypted form. Thus even if a malicious user were to obtain the computer or tablet with a cached instance of the application they would only be able to view the usernames, passwords and data in their encrypted form (provided the user has logged out or closed their browser).
Unfortunately at this time there doesn't seem to be any 'standard' protocol for securing HTML5 offline applications. Almost all literature warns not to store user credentials or any sensitive data on the client. However this is a paradox as this application must work while offline hence the data must be stored offline.
The security protocol implemented here has two keys, although once the first key is cracked it will be easy to obtain the second key. In the first level the user's password is encrypted with their own password as the key along with their username reversed as the salt. There is also a second key, 'data encryption key', that is returned from the server upon successfully authenticating to the server. This key is used to encrypt both the username and any IndexedDB data. This 'data encryption key' is inturn encrypted using the user's password. Thus if an attacker were to be able to decrypt the user's password they would then easily be able to use the password to decrypt the 'data encryption key' and then using the decrypted 'data encryption key' decrypt the user's username and any encrypted IndexedDB data. Only the encrypted form of the usernames, passwords and data then needs to be stored permanently on the client as by using the user's username and password entered into the login screen it is then possible to decrypt any persisted data.
However, after logging in, the username and password are stored in the client's session in their unencrypted form so that 1) the application can periodically re-authenicate with the server, this makes re-authentication seamless if there is intermittent connectivity and 2) retrieve the decrypted data encryption key at any time so as to be able to query/save the IndexedDB data and decrypt/encrypt it where necessary. If 1) weren't a requirement it should only be necessary to store the data encryption key in the session. This leads to a vunerability if the user has not logged out or has not closed their browser since a malicious user would then be able to view the user's password and username in their decrypted form (using a debugging tool). However this is not much worse than the same thing happening to a traditional online application that gives the user the ability to change their password, although normally a traditional online application has a session timeout so the malicious user would only have a limited time to act. Also if the browser crashes, normally it will give the user the option to restore their previous windows/tabs with their session information, hence the browser should be closed properly.
The protocol adopted above almost certainly does not follow best practices. For example the salt is not random (username reversed), is likely to be short, vunerable to a dictionary attack, the same may apply to the password (the strength of the password is a function of the server), there is no key stretching e.g. PBKDF2. However I cannot see how it is possible to follow 'best practices' and fulfill the requirements given the constraints imposed. It may be possible to improve the hashing a bit e.g. improve the salt, perhaps a combination of the username and a site-specific string however even that would require logic in the javascript that could be understood by a determined attacker. The Javascript can be obfuscated but that too only makes it more difficult but not impossible and any person capable of cracking the encryption keys would not find obfuscation of the Javascript much of a hinderance. Perhaps with some future clever inherent inbuilt support from the browser significant improvement will be possible.

Categories

Resources