3 ms·
Ask HN: How to store user/pass securely in the browser?
I'm working on a web app that will let the user interface with a 3rd party site via my service. In order for my service to utilize the API of the 3rd party, it requires the username and password for each individual user's account. I don't want to store people's private information on my service though. Not only do I feel personally uncomfortable doing that when other services want me to, and I don't want to be like that, I don't want to be in a position where someone potentially hacking my service can get all of my users' info.
I will have SSL setup for all communications between the user's browser and my service, and the API servers for the 3rd party are also via SSL.
I know I can very easily store the user's U/P in a cookie on their local machine(s), but that in itself presents security problems for them.
So, I need to be able to store the U/P somewhere. I don't want to make it so the user has to retype their info every single time they use my service, because it then reduces the click-and-go functionality of my service to zero.
What's the best approach in this kind of situation? Am I missing something obvious, or do I just have to bite the bullet and take the least-onerous option that's available?
- simonw 18y agoIf you can convince the third party site to adopt OAuth, do that. Otherwise, one technique you could use is to encrypt their password using a key derived from a hash of the password they enter. When they log in, set that hash as their cookie. Each time you need to use the third party password, read that cookie and use it to decrypt the stored password. Since you don't know their real password for your own app (as you only store a different hash of it), you won't be able to derive the hash used for the decryption process (note that this means you need to store a hash of their password for your own authentication using a different salt from the one you use to protect their encryption). With this technique, having access to your database is not enough to decrypt their third-party password. Unfortunately none of this resolves the root problem. Firstly, by asking users to trust you with their passwords for other sites you are teaching them to be phished. Secondly, if you turn evil (or someone evil acquires your site in some way) the server-side logic can be changed to steal the user's password.
- simonw 18y agoAnother downside of this approach: should they change their password on your site, you'll have to ask them to re-enter the password for the 3rd party service.
- tptacek 18y agoDon't do this: do what Colin said. Let k be 32 random bytes (using your OS's secure random number generator), store AES-256-CBC(k, [user, pass]), send k in a cookie over HTTPS with the "secure" flag set (that "k" is password-equivalent, and can't leak over an HTTP connection). Repeating Colin's caveat: the fact that you had to type "A-E-S" into your code to make the scheme work is strong evidence that you are doing something bad.
- cperciva 18y agoFirst, I think the idea of you making API requests using your users' credentials is a bad one from the start. If the third party in question wants to allow requests-on-behalf-of, they should provide a proper API for it; if not, you shouldn't be working against their wishes by impersonating your users. That said, if you really really have to do this: Have your users provide you with their username and password; generate a random symmetric encryption key; store (username, encrypted password) on your systems and send (username, encryption key) to the user as a cookie. This will give you safety against an attacker who can steal your database or the user's cookies; it won't give you any protection against an attacker who can steal both of those (that would impossible), nor will it give you any protection against an attacker who controls your server at a time when a user tries to use your service (again, that would be impossible). But I still think this is a really bad idea.
- geuis 18y agoThanks for the symmetric key idea. Yah, I don't like the idea of storing a user's credentials for a 3rd party service. Unfortunately the 3rd party requires http auth to access their api, and the app I'm working on interfaces with an individual's account. I wish the service had something like Flickr does for their API. The user could allow my app access 1 time, and it could work seemlessly without having to throw u/p back and forth.
- jrockway 18y agoFirst, I think the idea of you making API requests using your users' credentials is a bad one from the start. If the third party in question wants to allow requests-on-behalf-of, they should provide a proper API for it; if not, you shouldn't be working against their wishes by impersonating your users. This is true, but unfortunately we live in the real world, and hacks are sometimes necessary. Look at Mint.com, for example. Give some site all your banking details? WHOA THERE. But it turns out the service is very useful, and it works with pretty much every bank. If they had waited for proper APIs to exist, someone else would have beaten them to market.
- Herring 18y agoStore it encrypted on their computer then decrypt it each time it's sent to you? Maybe I'm missing the problem. One way or another you're going to have to hold it as plaintext to submit it to the other site. It's nice to hold it only in RAM, but the vulnerability is always there.
- bbb 18y agoExactly, and use public key crypto: 1) Generate public/private key pair for user. 2) Send public key to client. 3) Encrypt PW on client, store as cookie. 4) Store (user, private key) on your server. 5) Client now sends the encrypted PW whenever it is needed. 6) Server decrypts on demand, but does not store a local copy. Since you never relinquish the private key this is pretty much unbreakable for spyware going through a client's cookies. (Nevermind key loggers...)