Secure Way of storing Passwords to APIs without OpenID? - security

I asked a similar question here a while back but all the answers were offering OpenID which is nice but it doesn't work with services that require authentication that don't use it (such as EventBrite).
Say I want to create an app that lists your events from event brite, and their analytics (which eventbrite includes). Any person can sign up for this service to list their events. But since EventBrite doesn't have OpenID to authenticate, I need to somehow get the user login and password to EventBrite.
Some possible solutions are:
Store credentials in YAML like this. Easily hackable.
Have user enter in credentials into a form on my site, I save the credentials to my database, and use them to login to EventBrite. Easily hackable.
Have user enter in credentials and I pass them directly to EventBrite without saving, and I save the response header Cookies to the database, and when they expire, have them login again. Is this easily hackable?
This hypothetical service also wants to automatically check events (say via cron), so it doesn't depend on the user going to my site via the browser. So cookies or credientials need to be stored somewhere.
The thing is, after asking this similar question about confidentiality and security it sounds like you should never build an application that does what I'm describing. There's got to be some way building something like this is okay.
What is that way? What am I missing? Is it okay to go with #3 and save the cookies (but still needing the user to submit their email/password via a form which I send to Eventbrite)? What is an acceptable solution to the problem?

There isn't a secure way to do this. You can employ workarounds, but that's about it.
Storing passwords in YAML or XML in cleartext is definitely out
In fact, even encrypting and storing passwords is wrong. Your application would need a way to decrypt the passwords, so the attacker can also decrypt the passwords.
The recommended way to store passwords is Salt + Hash, but because it becomes unrecoverable, it is useless in your case.
Because of 2 & 3, no matter where you store the users credentials, you are vulnerable.
Storing the cookies instead of the passwords is a better idea. But again, this involves the password going through your website, which isn't good.
Given your situation, storing the cookie is a better approach. Use HTTPS throughout, even on your website. Its less than ideal though, and you and your users should be aware of it.

Eventbrite has recently release new documentation describing how to implement OAuth2.0 for cross-site user authentication.
I would recommend using our javascipt-based OAuth2.0 widget, which stores the user's authentication tokens in their browser's localStorage by default.
Since the auth tokens are stored in the user's browser, and are prevented from being accessed by other domains, it's not likely that there would be any security leaks.
The need for email and password combos are completely avoided in this authentication scheme.

Most sites only support direct login with the original cleartext password, so you have to get, store and provide that too. And I would never ever trust you with that.
The problem with your concept is that you require the password to be given to a third party. The solution is not to involve a third party, for example my browser is pretty good at storing and filling in passwords for me automatically (my hard-drive is password protected too). And they are dozens of other password wallet apps too. I wouldn't gain anything by subscribing, using your service.
Before going into such a business, consider you are going to be the #1 target. Facebook, Google are incredibly paranoid about security, spending a lot of time, money and effort to keep the logins safe. Do you have the same resources? Then you are a better target. Also by hacking your service, they immediately get multiple accounts, passwords of your users, also seeing who is always reusing its password.

For working with the Eventbrite API, I'd recommend ensuring that all connections are over SSL, and that you authenticate using a user_key rather than a username and password.
More information about authentication for the Eventbrite API is here: http://developer.eventbrite.com/doc/auth/
After logging in, users can find their user_key here: http://www.eventbrite.com/userkeyapi
This should prevent username and password information from being intercepted over the wire, or read from a local data store.

Related

Using cookies to securely store encrypted third-party passwords in DB

Obviously, storing third-party credentials of any kind is a major risk, and I'd like to avoid it as much as possible. However, I have an idea as to how it could be relatively safe and I'd like some opinions on this strategy:
MySite allows users to register with a username and password (or Facebook, whatever)!
If that user is also registered at site AllTheData.com (herein called ATD) with a username and password, they can give me those over HTTPS.
MySite receives the third-party credentials to ATD and does two things: creates a new crypto-key which it stores in the user's cookies, AND encrypts the username and password with that key and stores those encrypted values in the database.
AllTheData.com's Database might look like this:
| User | Password
| JohnDoe#gmail.com | p4ssw0rd_hashed
MySite's database now looks like this:
| User | Password | ATD_username |ATD_pass
| JohnDoe#gmail.com | another_p4ssw0rd_hashed| ct5lHMGymedITfElVA...|BHJCS38DkG7Zg0...
And the user's browser has a cookie with the key:
MySite_key: E3iKZxk2ZDD4EUb*fH$X6Mz5BO^iQeOM&V$lB0WAk4&WAB#A4QB8Yn7
Now when I need to access the service I pull out the encrypted values from my database, and I pull out the cookie from their request, and I can access the server! And of course, if their cookie has expired or they've cleared them out or switched computers or anything else then I have to ask again : ( But it's worth it if it means I don't have to store credentials in plain!
Have I done anything terribly wrong here? Are there any obvious problems with this plan?
Thanks!
I agree with CBroe's comment. There are much better ways of interacting with a 3rd party than forcing your users to give up their precious credentials. I would suggest looking into something like OAuth. It allows your users a lot of great features:
They only present their ATD credentials to ATD
ATD can give them control over what data or actions your system can do for them. The user has the power to revoke your system's access at any time.
Most of the big third parties that you would want to integrate with are already OAuth providers
Since you've stated that OAuth is not an option, I would try one more plan of attack before using your proposed solution. You have already admitted that your solution is pretty transient; once a user clears their cookies, you require them to log in again. If the service that you are calling creates a session on login, you could simply forward the users credentials to the third party and temporarily cache whatever token or session ID the service would normally return to users (I see no reason to store this in a database). You could then delete that token once your user logs out of your system. This keeps you from storing their credentials directly. It's not a great step up, but that's what I would pursue first.
If you combine this with your cookie encryption idea, I think you get a pretty good separation. You have the encrypted authentication token cached on the server, but it is only accessible to users that have the encryption key stored as a cookie. Like you say, that prevents your server from giving access to the third party if you are compromised. You don't really get any protection if your client is compromised, but I think that's unavoidable.
If the system requires credentials for every request, then I don't really see a better approach. You've done your homework and I don't see any better solution.
This is not too bad, although not the best way of allowing access to a 3rd party system.
Make sure that the MySite_key is generated by a cryptographically secure algorithm so that it cannot be predicted by an attacker, and protect this cookie the best you can. If there is any breach on your site, the cookie becomes very valuable to an attacker. Of course, how valuable depends on what data the user has access to in ATD.
That means implementing SSL/TLS on your site, enforcing the Secure Flag and HTTP Only Flag on the cookie and setting a HSTS policy. Also ensure that your site does not have any session fixation vulnerabilities - if one existed an attacker may be able to set their own encryption key for another user's account.
Make sure the encryption algorithm is also secure enough for your needs, such as AES-128.
Also ensure that your communications with ATD are over SSL/TLS only. Again, using versions of the protocol and cipher suites that are considered secure and not vulnerable to any downgrade attacks (e.g. FREAK).

Whether or not to use persistent cookies

We've just had a security auditor flag our use of persistent cookies to maintain login state in our web application. As a bit of background, our web application is multi-tenanted, but no (or not many) operations are destructive. There may be - depending on the tenant - sensitive information available through our portal.
Back when we designed our application, we discussed the use of persistent cookies, and decided that we should based on usability. We didn't, and still don't to a degree, deem the information available as sensitive. Our users are fairly novice and we were more concerned with having hundreds of reset password requests.
Is the use of persistent cookies for logging in deemed a security risk? Is the trade off in usability even a discussion when we're talking about operational data of some fairly big businesses?
We haven't had any questions regarding persistent cookies before - not from any of our clients. Would it be worth implementing a 'tick to persist' that defaults to off to satisfy both sides?
Persistent cookies, are used for a variety of reasons, and to support numerous functionalities. If your app has absolutely nothing "sensitive" then, you can use persistent cookies for permanent authentication, and then issue re-authentication to access user account details, or do some changes (i.e. change password, or e-mail address). You mentioned that your users, are novice, so I don't think that they know that if someone else uses their browser they will also be authenticated without knowing his or her password (I would point it out to users).
But there is a reason why security critical apps like online banking, do not issue a persistent login cookies, although they could, because before making any changes to your account balance you have to re-authenticate out of band (via mobile, or some form of OTP). But it's considered insecure, and maybe it is because knowing someone's balance is already invading their privacy.
So if your app is not controlled by any government authority, and you're not bound by any law in your country, and you implement re-auth on sensitive parts of your app, then issuing 2-3 week persistent cookie for authentication, is not a significant security threat.
If persistent cookies are not to be trusted, Fatfredyy's suggestion sounds great.
However, if the problem is unsecure use of persistent cookies, why not encrypt them?
Upon either ticking "Remember me" or by default a cookie is generated including some unintelligible unique ID for the user and an encrypted part containing verification. The key to the symmetric encryption is stored in the DB with the user ID and never shared with the user. When the user revisits, you use the ID to access the key and decrypt the rest, verifying that no tampering has been done.
When an attempt to fiddle with the userid has been identified, display a message to the user and change the encryption key, requiring the user to re-authenticate.
This would enable you to use persistent cookies while not compromising the users.

Plain English explanation for usage of OAuth in conjunction to an internal user management

I'm new to OAuth, and although I have scanned through many documents, I don't seem to have yet a good architecture / design to a secure web application, answering most/all of OWASP Top Ten
My newbie questions are
Why can't I just rely purely on OAuth? why do a user needs credential in my own application?
If I do, do I need hash / salt anything if I save it? I don't store any passwords, but what about tokens?
I still need to persist the users so they won't login everytime, (like in OS) - do I
Somehow use the OAuth token (save it? does it make even sense)?
Or use the plain old httpOnly secure cookie (if so, what happens if they log out of the Oauth provider? shouldn't I in this case ignore my cookie and let them log out?
How do I implement logging out? I can't force them to log out of the OAuth provider, and if I only delete the httpOnly cookie / invalidate their session locally, is that enough? and security issues?
How do I implement single sign on? I don't want the user, after approving to click again "log in using Facebook / Twitter / Google" I want an effect similiar to SO (page refreshes and "welcomes you back" what are the best practices to do that? Why does SO refreshes the page (I assume it has to do with the fact it needs to be client side, but I don't fully understand how it works to even know what to ask)
I guess I have a lot to learn, but reading on so many potential security issues, and having to master so many different topics seems like a good potential for me missing something that someone later will exploit.
Is using a framework such as Spring Security, or using Lift's built in user management going to save me all this headache? or do I have to know exactly what I am doing to avoid things like Session Fixation, Cross Site Request Forgery, Cross site scripting, Rainbow tables and other things I only remotely get...
Why can't I just rely purely on OAuth?
From a service providers perspective, OAuth is a means of controlling access of third party applications to the business logic. The end user does not have to give out his password to the third party app, and the access can be controlled. For example, the provider could restrict the access to only parts of the service for limited amount of time.
If you write a third party application, there is no strict need for you to have your "own" user artifacts. You can rely on the users that authenticate your application.
You could require that user's have an account with a provider such as Facebook or Twitter and not implement any password stuff yourself.
(You probably need some sort of artifact to represent a user, it should in this case contain information about how that user authenticates your application, for instance an OAuth token, or an OpenID URL).
If I do, do I need hash / salt anything if I save it? I don't store
any passwords, but what about tokens?
Just to clarify, in OAuth a token is typically both a key and a secret, and they are needed in cleartext to sign requests (there are differences here depending on which version of OAuth you use). So you can store them encrypted, as long as it is reversible for you.
I still need to persist the users so they won't login everytime, (like in OS) - do I
somehow use the OAuth token (save it? does it make even sense)?
Yes this makes sense, a token represents your applications access to a specific user's data. Save the token if you want to keep a "session" alive.
How do I implement logging out? I can't force them to log out of the OAuth provider, and if I only delete the httpOnly cookie / invalidate their session locally, is that enough? and security issues?
There is no concept of "logging" out of OAUth, a token either has an expiration time or not. You can of course "log out" by simply choosing to forget the token. The next time you will have to redo the authentication. You cannot force users to invalidate an access token, unless the provider has an API for that.
You could save the token in a cookie, but I would use other unique identifiers for the session you want to keep alive. You can persist the details of the tokens server side. The information you store in your cookie shold make it possible to retrieve the token you need.
How do I implement single sign on? I don't want the user, after approving to click again "log in using Facebook / Twitter / Google" I want an effect similiar to SO (page refreshes and "welcomes you back" what are the best practices to do that? Why does SO refreshes the page (I assume it has to do with the fact it needs to be client side, but I don't fully understand how it works to even know what to ask)
If you save a token in a database, save an ID for that token in a nice secure cookie. When a user goes to your service, use the information in the cookie to make a call from your service, to the service provider, to check if the token is still valid. If so, you have established enough trust for you to "log in" the user in your application without having to go through the pain of the OAuth process again.
And as a side not, StackOverflow uses OpenID and not OAuth for user authentication. OAuth can be used for the same purpose but is mainly a specification for application authorization.
I hope this helped, and don't sell yourself short. This site is for posting questions, not for appearing all-knowing.

How should I savely store encrypted user data on my server, and serve it only to the right user?

Let's assume I must store user's sensitive data, which was optionally encrypted on the client side.
Encryption (optional) should be done with user's passphrase.
User login (optional) should be done with user's password.
Notes:
A plain-text password is not stored on the server or transferred over the network.
My options and their drawbacks:
1. No authentication, Client-side authorization:
The server gives the data to everyone, but only the original user have the means to decode.
Data can be used by anyone to try to crack the encryption - not the best way to secure it.
2. Server-side authentication, no authorization:
Server stores user's password to access the data, and only gives the data to the user that can provide the right password.
Users don't trust the network for transferring their data without encryption.
3. Authentication and authorization:
Server stores user's password to access the encrypted data, the encryption is done using the passphrase that is different from user's password.
Good security, but users don't want to remember two passwords.
4. Authentication vs. Authorization:
Server stores user's password to access the encrypted data, the encryption is done using the same password.
Users are happy. Some security concerns.
I prefer the latest fourth option, but my concern is:
What if the server will get compromised, how can I be sure that encrypted password and encrypted data can't be used together to break the encryption?
How can I make it harder to break the encryption?
Some thoughts:
Use different encryption algorithms for password and data.
Add fixed string to the end of the user's password before encryption.
Pad user's password to some length.
EDIT:
The system should be very similar to a backup system that should be secure from all sides: the server should not be able to read the data, only the original client should be able to access the data and man in the middle attacks should be prevented. So if someone hacks the server authentication or the client encryption, the data should not be revealed.
It should be web based, so the man in the middle attack should be prevented with HTTPS.
To prevent server hacks revealing the data, the data is encrypted in client-side.
To prevent client encryption tampering, the access to the data should be protected on the server side with some log in and password or a token (may be unique URL).
#Vitaly, permit me to clarify some terms before I answer, as you seem to be using a different meaning for some than is commonly used.
Authentication - the process of proving who you are (more accurately, that you own the identity you are claiming).
Authorization - the mechanism used to restrict, control, and grant access.
Encryption - a mechanism for protecting data, even from someone who has access to it.
Now, allow me to rephrase your options, and then I'll suggest something else:
No Authentication, No Authorization, Client-side encryption
Server-side authentication, Server-side authorization, Server-side encryption
Server-side authentication, Server-side authorization, Client-side encryption
Server-side authentication, Server-side authorization, Client-side encryption using server credentials.
Now, I think it can be clearer where each one stands.
In general, you really want to follow the "best practice" (dont get me started on those) principle of "Defense in depth", i.e. dont use only encryption, or only access control, instead use both! But, as you pointed out, this can be in contrast (if the user is required to remember TWO passwords) to another principle, "Keep Security Simple".
Without trying to be TOO annoying, you didn't give much information in the way of your environment. For example, is this e.g. a Web application? If so, why is SSL/TLS not enough encryption for you? Or is this a question of users uploading personal data that you (and your system) should not see either (e.g. a backup-type service)? In which case client-side encryption would be necessary...
So, (finally) my proposed options, depending on your environment / requirements:
If you can, rely on secure protocols (e.g. SSL/TLS) for encryption. Use server-side authentication + authorization, protocol encryption.
If your system needs to further protect this data, e.g. credit cards (note that I am not currently a PCI:QSA ;) ), use the previous option, and in addition server-side encryption using a server-generated encryption key (NOT the password) (and of course protect that).
If the data needs to be protected FROM your system, you will need to do client-side encryption IN ADDITION to server-side authentication+authorization (your option 3 as I restated it).
However, you don't necessarily need to force the user to remember an additional password/phrase. Again, depending on your environment, you might be able to consider some form of key stored on the client, e.g. a certificate in the user's certificate store / keyring, or even stored in a protected configuration file; a key based on biometric data (not easy but i've seen this done successfully, though it has its own set of issues), out of band key distribution (e.g. via cellphone), etc. This would enable you both to use strong keys, prevent the server from accessing those keys, not require the user to remember two keys, and doesn't re-use a single password for different usages in different contexts.
You could take a look at zero-knowledge protocols for authentication, in particular to the Secure Remote Password protocol, which makes it possible to perform password-based authentication without revealing the password to the server. This way the same password can be used both for authentication and for deriving a data encryption key.
Also, you could take a look at the Clipperz online service, which implements something similar to your needs and is also open source.
Use option one and make the URL for the data contain a long random string. Anybody who knows the random string can get the data. Of course, only the client who created the data is going to have that URL right off.
If someone wants to give someone else revokable access, allow them to generate a new random URL and provide a means for them to name that random URL and revoke its ability to get at the data.
Capability based security is easier to get right, more flexible and makes more sense to users. There is a really excellent YouTube video about capability based security and a nice website with some essays about it.

How to securely store a user's OpenID

I'm writing a web application that allows anyone to register (using their OpenID). When a user registers, their OpenID is saved in a MySQL database.
My question is: In which format should I be storing a user's OpenID value?
If someone were to gain access to my database (I'm planning for the worst case scenario) - would it be an issue that the user's OpenID can be viewed unencrypted? Should i be encrypting it when it goes into storage?
There is no real benefit in protecting their open id: that's the whole point of it!
OpenID is made so that the "secure info" is not available at the intermediary sites where you use it - the only secure info is held at the OpenID Provider (the site where you actually enter your password).
A compromised database on your site means that the attacker will know who your users are, but nothing more, nothing less.
This is one of those things that is up to personal taste, but MySQL do offer some encryption functions you might wish to take a look at.
http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html
In which format should I be storing a user's OpenID value?
Even when someone has access to the openid's stored in your database, this information will be of no use to him as it is only a url which asks for user authentication details when executed.
So you need not worry on that.
The openid providers will take care of that if the details entered are correct or not.

Resources