I’m attempting to design a single sign on system for use in a distributed architecture. Specifically, I must provide a way for a client website (that is, a website on a different domain/server/network) to allow users to register accounts on my central system.
So, when the user takes an action on a client website, and that action is deemed to require an account, the client will produce a page (on their site/domain) where the user can register for a new account by providing an email and password.
The client must then send this information to a web service, which will register the account and return some session token type value.
The client will need to hash the password before sending it across the wire, and the webservice will require https, but this doesn’t feel like it’s safe enough and I need some advice on how I can implement this in the most secure way possible.
A few other bits of relevant information:
- Ideally we’d prefer not to share any code with the client
- We’ve considered just redirecting the user to a secure page on the same server as the webservice, but this is likely to be rejected for non-technical reasons.
- We almost certainaly need to salt the password before hashing and passing it over, but that requires the client to either a) generate the salt and communicate it to us, or b) come and ask us for the salt – both feel dirty.
Any help or advice is most appreciated.
3
What exactly do you need? To be sure that the password won’t be read by a man in the middle? To be sure that the man in the middle wouldn’t be able to log on?
If all you want is preventing the man in the middle from reading the passwords, just hash those passwords. It’s as easy as that.
You may also want to avoid the man in the middle from getting the user name. Here, you wouldn’t be able to transmit only the hash, but instead, you can encrypt the user name/password pair with a public key sent to the client, given that the server will have the private key for the decryption.
If you want to prevent the man in the middle from logging on, then the task is slightly more complicated. You can still use public/private keys, but:
-
either the public key should be communicated in advance to the consumer of the web service (which has a drawback of using the same key pair again and again, as well as the difficulty of transmitting the private key by some other channel where the man in the middle cannot catch it),
-
or the consumer of the web service can send a second public key which will serve for the server to encrypt its own public key in the response.
4
- Client-Side SSL (public-key) Certificates are the only scheme that protects clients against man-in-the-middle attacks, thus making them the most secure. Edit Last time I checked, Verisign was chaging $100-200 per client certificate End-Edit. If clients are humans, you can install the certificate in their browser and move it to a different browser at any time. It’s a little like a more secure, universally accepted cookie. If you read the OpenSSL manual, you can use OpenSSL to become your own Certificate Authority and generate and accept your own certificates, but you have to be very careful to do everything right (any mistake can undermine the security of the system as seen repeatedly in the news). When I last checked, Chrome required the user to use the command line to set a client certificate, but all the other popular modern browsers could set certificates through JavaScript.
- Client-side cookies. Clients still log in the way they do now, but the server sends them an encrypted cookie (the server does all hashing and salting and chooses what data to hash and salt). Most people go this route, probably because it is easy to implement. When you see a “Keep me logged in” checkbox on the login page of a web site, this is usually what’s happening.
- OpenID has complete documentation and implementations available. It allows you to leverage one account (which is OpenID enabled) to log in many places. It has the advantage that the user only needs to “remember” one password (I hate the word “remember” with passwords – people should be using a password manager to store passwords that they cannot remember). The big disadvantage of this is that if someone compromises the master account, all connected accounts will fall with it.
- ActiveDirectory/LDAP This is the most popular and traditional form of single-sign-on for internal applications within enterprises. I think it was created by Novel at a time when managing an address book of names and phone numbers (the “Directory” in LDAP) was considered a big deal. This was a time before computer security was even much of a consideration. Microsoft’s Active Directory implementation has shipped with all their major operating systems for over a decade. People can be automagically signed-in to AD/LDAP-enabled intranet sites just by being signed into their desktop. It requires all clients to be on the same local network, or at least for the AD/LDAP server to be accessible to the web server checking credentials. It provides no security, or really bad security in and of itself. You absolutely must test that your authentication packets are encrypted by the transport layer (ssl over https) and test your server to be sure that it will NEVER accept any un-encrypted connections. The idea of sending people’s desktop login information freely in plain text over the network makes me really uncomfortable. It almost cheapens the word “exploit” to say that this weakness has been exploited many times over the years. If you go this route, I believe that LDAP clients are available for Linux and Mac as well as Windows.
4
Look into OAuth which is designed for this permission-to-do-something role. You don’t ask for a user identity, instead you ask the user to provide you with a token (that you trust) that you can use to determine the permissions you’re willing to give that user.
All the security encryption gubbins is handled the the framework so you don’t have to worry too much about just how to encrypt the communication using such a framework.