Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Building and implementing a Single Sign-On solution (merbist.com)
67 points by raganwald on April 4, 2012 | hide | past | favorite | 42 comments


The cookie doesn’t need to contain a lot of data, its value can contain the account id, a timestamp (to know when authentication happened and a trusted signature) and a signature. The signature is critical here since this cookie will allow users to be automatically logged in other sites. I’d recommend the HMAC or DSA encryptions to generate the signature. The DSA encryption, very much like the RSA encryption is an asymmetrical encryption relying on a public/private key. This approach offers more security than a shared secret like HMAC does.

"Yes, definitely build custom crypto for your single signon system, especially if you think HMAC is an "encryption" but just "not as secure" as DSA because it's "shared secret"."

SSO schemes are one of the primary reasons people build crypto for their web apps (they don't want the database dependency between the shared apps). These schemes usually fail calamitously, sometimes a year or two into production, when your app coughs up the ability for one person to log in as any other person without a password.

If you have a real app with a real customer base or doing real revenue and feel the need to put something like this in the field, please ping me. I'm not going to try to charge you. I may try to talk you out of it, though. I will absolutely talk you out of using RSA or DSA.


Thanks for the expert feedback. From my very limited sec experience, I saw account_id in cookie, and identified that as a red flag. OTOH, I think a random token in the cookie, identifying a server-side session that stores the account id, would be a good approach, as it's the classical HTTP auth implementation. For example, what the Rails tutorial describes [1].

For SSO, the other apps can ping the cookie-originating app: "Hey, who is this browser with this cookie token" ?

[1] http://ruby.railstutorial.org/


That's a fine approach, but developers push back on it because it requires all the apps in the SSO federation to be connected at all times. Most shops should just accept that requirement and get on with their lives, though.


This is more or less the way SAML [1] works, at least in one of it's protocols. The authentication server redirects (after successful login) to the initiating service and supplies an assertion-token, often with limited validity. With that assertion token more data can be asked from the servers to the auth-server directly. No account_id's go over the wire, the cookie needs only to be valid on the authentication server. And you should really need it, it's not much fun to implement.

1 http://en.wikipedia.org/wiki/SAML_2.0#Artifact_Resolution_Pr...


Any thoughts on Atlassian Crowd?

http://www.atlassian.com/software/crowd/overview


I've never gotten a chance to look at it. Presumably someone has reviewed it; Atlassian's a decently big company. You could probably ask them.

(Note also that if we had reviewed them, we probably wouldn't be able to talk about it here. But: we haven't.)


Encryption is some funny stuff. I worked on a team that implemented SSO between an ASP.NET app and a PHP app. We used AES with a shared key and IV. That was it. We just shoved the encrypted user token and timestamp into a domain cookie.

But I guess we should have also signed the encrypted value to know that we generated it?

What's the process to break this scheme?

1) Know what type of value is being encrypted: email, username, tokenid 2) Gather several pairs of usernames/encrypted usernames 3) Use some brute force method to uncover the key and IV 4) generated fake cookies since you know the key/IV


It's trivial to figure out what encryption scheme† is being used for a cookie or HTTP parameter as long as any portion of the plaintext being encrypted is influenced by something an attacker can control directly or indirectly.

If you're not authenticating your ciphertext, you might as well not encrypt it; attackers can rewrite the plaintext, if not outright decrypt it (the adaptive chosen plaintext attacks on AES block modes all rely on messages not being authenticated).

I'd enjoy talking more about the methods to break this stuff but am concerned that HN will read that comment as "well then we just need to stop those attacks and then we're safe". I have roughly 5 years of experience on HN to back that concern up. :)

(At least, with enough specificity to attack it.)


Thanks. I Googled Adaptive Chosen Plaintext Attacks, and it seems to me that the statement, "attackers can rewrite the plaintext" needs to be qualified with, "given liberal access to the encrypting mechanism", which I guess means free access to create new accounts in an SSO situation (or access to some other web-method that used the same encryption).


"Chosen plaintext" means that the cipher can't tell if what it has decrypted was what the original authentic encryptor encrypted. "Adaptive" means that the attacker gets repeated attempts to break the same piece of ciphertext. The canonical example of an adaptive chosen plaintext attack is the AES CBC padding oracle, but there are multiple others.


Thanks for correcting my abuse of language. I should have reviewed my post in detail. I did fix that now.

That said, while I appreciate your perspective, I'm quite disappointed that you aren't offering any solutions besides asking people to contact you.


"Abuse of language"? You suggested that HMAC was an alternative to DSA. That's not a semantic nit. Signatures, by the way, are not the same thing as message authentication codes. And like I said: nobody should be using RSA or DSA for SSO tokens.

Offering solutions on how to implement a secure single signon scheme with RSA or DSA on Hacker News is like explaining how to perform an appendectomy in Youtube comments.

Sorry, not interested in hurting people.

I know I sound super snippy here, and I'm sorry about that, but this problem comes up a lot. We keep finding applications that get almost everything right; locked down database layer, bulletproof authorization, reliable output filtering to stop Javascript injection... and then they go build single signon, and 3 days after we see that we can turn a guest account into the sitewide admin.

People would be a lot better off if they did not try to build this particular feature themselves. (We don't build SSO systems for people, in case you think this is a sales pitch.)


Can you please explain why using DSA to sign SSO tokens is a bad idea?


Bignum cryptography is more dangerous than block cipher cryptography and (in secure systems) invariably depends on hash functions anyways (they're the worst of both worlds). The idea that public key algorithms are "more secure" than "shared-key" (symmetric, block cipher core) cryptography is exactly the opposite of true.

Meanwhile, the utility of public-key cryptography in SSO systems is minimal. Public key is useful, and sometimes the only viable solution, when you have a potentially unbounded population of verifiers or signers. But that's never the case in SSO schemes, which have a bounded number of cryptographic participants (or, if they don't, are badly broken).

Long story short: public key crypto is a last resort for systems that can't be deployed in any other way.


The idea that public key algorithms are "more secure" than "shared-key" (symmetric, block cipher core) cryptography is exactly the opposite of true.

That seems backwards to me. How is having one key that can sign things be less secure than having multiple? If someone pwns a box with the shared key, they can forge credentials. If someone pwns a box with the public key, they can't. I would make sense to me that you'd want the important key that can be used to sign credentials in as few places as possible.


After fielding a custom-cryptography single signon system for your Ruby applications, you think your biggest concern is "how well will the system survive the loss of one of my app servers to an attacker"? Let me help you out with that: you won't survive the loss of one of your app servers. You're going to have to rebuild and rekey everything.

No, the biggest concern you have doing custom-cryptography for your Ruby apps is that the cryptography itself is going to hand attackers control of your app servers. Which, from experience, is somewhat likely. More likely if you haplessly use RSA or DSA.


Obviously you're going to rebuild compromised servers and change all the keys... as soon as you find out you've been hacked.

What about before then? You're advocating a scheme whereby if any verifier is compromised, the attacker can forge tokens. This isn't the case with a system that uses asymmetric crypto.


You're going to have to re-key because as soon as you got hacked the security of your SSO scheme is likely nil. When you find out about has nothing to do with anything.

In any case, no part of block cipher crypto requires every pair of participants to share the same key --- even in the unlikely even that you needed all-pairs keys (virtually all SSO systems have a star topology).

The idea that a system is going to resist forgery because it uses public key cryptography would be amusing if it wasn't so common. In reality, cryptography does not work the way _Applied Cryptography_ says it does; it works more like the way _Cryptography Engineering_ says it does. In other words: it conspires at all points and at all times to fuck you.


I'm seeing a lot of polemic and handwaving but missing substance, sorry.

What is the actual problem with RSA in this context, assuming OpenSSL is used correctly? What are the common pitfalls?


I'm definitely not providing all the substance, you're right.


I take it you're being sarcastic, but the negative comments you're receiving are I think because you departed from giving advice on implementation and strategy, and attempted to give a piece of cryptographic advice.

The only way anyone gets to imply that public key crypto is less secure, or more dangerous, without being challenged, is if a new attack is presented. Otherwise it's all innuendo and handwaving.

Most apps and sites may not derive any advantage from public key crypto, but you can't say that for sure until you see a site (or SSO multi-site) design.


I'm not being sarcastic. I'm simply not interested in going into more detail on this topic.

I don't think anyone who's opinion I care about on HN thinks I'm dealing in innuendo on crypto topics.


That didn't really answer my question, and you're changing the argument. You said, paraphrasing, "public key is less secure than shared key", which doesn't really make sense, for the reasons I already mentioned. Saying its all irrelevant because my app is already insecure is totally orthogonal to this sub-thread.


No, that's not all I said.


This might be the right place to ask but ... is there a reason people keep reinventing SSO?

It's 2012. The first place I saw SSO was on a Banyan VINES network, in 1990. Years, I hasten to add, before NetWare figured it out.

We've got it, still, in the enterprise. It's now Active Directory, but I can use my same credentials for login and auth on Windows clients, unix machines, two different web apps from as many external providers.

Note, I have no idea how the web apps obtain my login credentials, save that the AD guy and the web guys did some black magic behind the scenes.

Why do people keep re-inventing SSO, sometimes badly? No way to make a black box that Just Works?


Not only what tptacek said, but it's somewhat related to NIH syndrome. People look at the specs for standards like OpenID, OAuth or SAML2; think it's way too complex; and decide they can write something much simpler to suit their needs. After dealing SAML myself for a couple years, I agree it's huge and possibly over-engineered, but it also has years of work put into it, and there are well-tested implementations that you can use, just maybe not in your favorite language.

Note: I'm talking about Web-SSO. Host SSO pretty much consists of LDAP+Krb5 (which is the basis of Active Directory authentication), or just LDAP. Everything else is pretty much dead, though NIS still sticks around the *nix world due to it's ease of configuration.


With a lot less experience to you I can relate to the NIH syndrome, but I don't think it's just the specs, it's the resulting implementations. Just go look at the .Net one that everyone recommends you use:

https://github.com/AArnott/dotnetopenid/tree/master/src

Over-engineered specs seemingly result in over-engineered code. Not that I really get why they made the client and the provider one big project in the first place.

Having mucked around with OAuth on a couple of .Net projects it's just a nightmare to use. If something goes wrong and you try and dive into that code, woe betide you. It's like a rabbit warren. Just to figure out you aren't properly encoding the &s or something.

Having used the v3 calendar API recently it's interesting to see Google now just release essentially very simple libraries that just deal with the integration for you. It's like even they've given up trying to get people to use OAuth, where the google groups were littered with 'can't get auth working' and so just hand-wave over it.

Personally I think it's at the SOAP stage that data exchange formats went through, sounds simple but somehow is extremely complex. I'm hoping that the JSON equivalent will come out soon.


Because standarized SSO systems would require the maintainers of multiple unrelated app stacks to agree with each other about something.


The only thing that needs agreement is the protocol. There are two choices IMO. SAML, or WS-Federation. SAML2 is pretty good but limits implementers to the passive requestor profile (it relies on the browser for the HTTP 3xx redirects) and means you can't use services[1]. It also doesn't do attribute provisioning (something U-Prove can do). The SAML protocol also mandates use of SAML tokens. WS-Federation on the other hand lets you use any token you like. And it supports services.

[1] TBH I haven't looked at SAML for a long time. It may well have come along by now.


You were thinking maybe PHP, Rails, and Django devs might decide to adopt a WS-star XML-hell enterprise standard?


I wasn't thinking anything - I have no idea what your requirements are.

Slide 12, and slide 61: http://wwww.wittenburg.co.uk/Presentations.aspx

[Edit] Maybe that answer was a bit trite.

As mentioned, I don't know what the requirement is. The article mentions Ruby, Python and Node, but also suggests those selections are random to introduce complexity.

Would I choose WS-Fed? Depends.

Maybe, if the IDP uses AD. The benefit is that you can use ADFS and only code out the relying party. Definitely, if the solution is service-based. And also definitely, if a). I need a token other than SAML or b). I'm doing anything with Azure or Office 365.

I guess a more interesting question is why I'd code web SSO from the ground up when there are two stable protocols out there. I wouldn't. I'd use what brains more capable than mine have already designed. Something that has been out there for a while, and has proven itself to scale and be secure.

Security is very compelling. WS-Federation is used to protect some very, very sensitive public sector services. And I'm talking a lot more sensitive than the HR solution I built for the UK government.


By the way, I should've mentioned this -- you can get WS-* -based federation without having to "adopt a WS-star XML-hell enterprise standard".

The way you'd do that is by putting ADFS or another WS-Federation-capable proxy (UAG, maybe) in front of your Django/Node.js/etc. app. All you need to do then is to deal with claims. Not even, if you have something like UAG transform claims into AD roles. Note that that approach doesn't rely on AD. You could use a flat text file, XML or SQL Server.

And while I'm here - coding up something that uses a non-ideal technology (XML) is still a better option than re-inventing the wheel. 'Specially in this context.


Well, the question was asked why Ruby, Python, and PHP apps don't have an existing SSO standard. I guarantee you WS-foo is never going to be that standard.


That's fair enough. But then accept that I will refer you back to slides 12 and 61 ;-)


What is the 'de facto' answer for environments where AD isn't present?

I was going to say something about AD not supporting SAML, or federation, but it appears that my knowledge is dated. But in an enterprise where there are no Windows machines (to my knowledge,) much less Windows servers, what's the fill-in?

*Edited the snark out.


I think the standard UNIX-flavoured solution is LDAP+Kerberos, which is pretty much AD without the gratuitous incompatibility and useful extras.


A lot of enterprises use SiteMinder (aka ChannelSecure), which used to be Netegrity's before they got bought out by CA. It supports both Apache and IIS, although I'm not 100% sure what the policy servers run on, it might be Windows. But I have seen LAMP apps that integrate with it, for example. It really is just an intercept-and-forward system that functions as a module on the web server and puts a few things on the HTTP headers to allow apps to handle authorization by themselves.


After about a decade of testing people's web applications, SiteMinder has defnitely emerged as the standard third-party tool for SSO.

Many years ago, it seemed like people were fairly evenly split between Siteminder and another one (I think it was called GetAccess, but the fact that I can barely remember it is probably an indication of it's current popularity).

Siteminder is a good solution (and I've probably tested about ~150 web applications over the years that are using it).

It's caused my attack plan to go from "Let's see how fundamentally broken this company's home-grown SSO solution is" to "Oh good, they use Siteminder. Let's see what areas they haven't implemented it properly in."

That's an important distinction, and the bulk of issues I've found with Siteminder over the years have all been in identifying specific pages or transactions which aren't properly using the SMSESSION. I found a forehead-slapping issue recently where there was one page that wasn't properly validating the SMSESSION (it was just checking to see that it existed). That page happened to be the "reset password" page, and it was possible through a series of redirects to modify anyone's password to whatever you wanted, even if you didn't have a valid account on the system.

And that's kind of the problem, which is that even using someone else's SSO mechanism (which, again, Siteminder is as good as any one I've seen over the years), If you've screwed up the implementation for any transaction or on any page, you're still screwed.


Good question.

I'm familiar with two 'unix' networks that stood apart from the windows networks in an enterprisey setting.

- NIS+

- Scripts to copy a 'master' /etc/passwd to all other unix hosts. Keep the master under version control.

But I've been here for over a decade. When I got here we were using vintella which hooks the unix hosts into AD.


You might also want to examine the OpenID way, in which case you can use for example, this https://github.com/jondot/passage, or this https://github.com/dbloete/masquerade (depending on how complex the project you want to build on)


Would openID be a good option for a SSO solution? If so what would be the best way to implement a openID server using Ruby?


Check out https://github.com/dbloete/masquerade

I haven't used it.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: