What is meta? ×
Meta Stack Exchange is where users like you discuss bugs, features, and support issues that affect the software powering all 130 Stack Exchange communities.

SO and SU just told me I've been logged in. I'm guessing because I'm already logged into my Google account... but how does SO know that?

share|improve this question

migrated from stackoverflow.com Sep 11 '10 at 22:59

This question came from our site for professional and enthusiast programmers.

2 Answers 2

up vote 104 down vote accepted

I'm going to provide more than just the technical details here, as I think there are alot of implicit assumptions about global login that aren't quite correct out there.

Accordingly, this is going to be really long.


Design Requirements

  1. A user having logged into any SE-site will be automatically logged into every other SE-site on which they have an account
  2. Site level logins must not fail if the global login system is down
  3. Must not present unexpected sites or information to the user
  4. Must not degrade the anonymous user experience

1 is obvious, 2 is due to a strong desire not to introduce a new network wide dependency, 3 is shorthand for "don't scare off the user," and 4 is an acknowledgement of how much of our traffic is from anonymous users.

These are taken as axiomatic, any scheme that didn't fulfill all 4 was immediately discarded.

The Scheme

Initial Login

  1. Login as normal (unmodified code path)
  2. At the end, the user is given a global login token (attached as a cookie)
  3. The next page the user visits takes that token, and (via an IFrame) shovels it to StackAuth (stackauth.com)
  4. StackAuth verifies the token, and attaches a session key via localStorage

Visiting a New Site

  1. User hits any page on the site
  2. Some javascript hits StackAuth via an IFrame
  3. StackAuth checks localStorage for a session, and sends it to itself if it is.
  4. StackAuth validates the session, and (if valid) passes a login token to the SE-site via postMessage
  5. The SE-site validates the token, looks up the user, and (if valid, and the user is found) logs the user in

Some Technical Details

  • Every step that passes data between the SE-site and StackAuth (I3, V2) uses a one-time-use request token to prevent XSRF attacks.
  • All tokens are opaque to the user (more details below)
  • The entire Visiting a New Site process is suppressed on a site after it is run once in a browser session.
    • The idea is that once it has failed, the user is probably anonymous and it'd be a waste to keep trying. We allow users to force a login attempt by clicking "log in" to work around edge cases.
    • This also implies that if you visit one site, then log in on another, and then go back to the first, you'll need to click "log in" to trigger the process.
  • To see if your system meets all requirements, see the Network Login Troubleshooting page.

Tokens

  • Request Token Contains
    • The requesting site
    • The IP for which it is valid
  • Login Token Contains
    • The generating site
    • The destination site
    • The actual login credentials (roughly equivalent to the user's OpenId)

Crypto

Security Discussion

We're in a pretty novel position, as we cannot trust the user despite acting on their behalf. Conceptually, we have two of our sites (some StackExchange site, and StackAuth) communicating using the user's browser as the channel and as a data store. Accordingly, everything that passes through the user's browser (which is everything, really) must be cryptographically secure.

Acknowledging this, we turned paranoia up to 11 and went full on "defense in depth*." If anything looks "weird" we bail, and the user degrades to using manual logins.

Things We Check

  • Your HTTP Referrer is one of our sites
  • Your IP has been held constant between subsequent requests to the SE-site and StackAuth
  • The sites encoded in the tokens are correct
  • The tokens are no older than X minutes (its really tight, but subject to change)
  • Nonces are never reused

Third-Party Cookies, SSL, and More

Some responses (on the blog, and elsewhere) ask why we don't just use cookies (or cookies set via images, IFrames, script tags, link tags, etc.). These are all third-party cookie schemes, and they just plain don't work. Trust me, everything that's been suggested thus far was actually tried at some point and found lacking.

With some song and dance you can get Chrome, Firefox, and IE to accept third party cookies (most of the time anyway). Safari requires that you set these cookies via an IFrame, and convince the user to interact with it; which is quite possibly the suckiest user experience you can come up with for a global login scheme. A browser as popular as Safari just plain not working with any third-party cookie scheme just kills the entire technology for us.

There have been some SSL questions. The short of it: we don't use SSL anywhere in global login. SSL protects against man in the middle attacks between the user's browser and a website. As noted above, we don't trust the user so SSL doesn't actually solve any of our security problems. Also, currently our normal user session cookies (usr on StackOverflow, for example) aren't sent over SSL; any attack against global login would work equally well once a user is logged in "normally". Naturally, if we switch to SSL across the sites we'll do the same in global login but right now it'd be pointless. SSL also imposes non-trivial performance penalties.

Inquiries have been made about open-sourcing our implementation of this scheme, or allowing third-parties to authenticate users with it. In short: no. This scheme makes very hard assumptions about how a site works, and thus isn't easily open source-able. For third-party authentication, I'd much rather use something more "standard" like OAuth2.0 (which isn't acceptable for us in network, since it assumes a many-to-one consumers-to-providers scheme).

*The idea is that an attacker has to jump through a lot of non-trivial hoops before they can even start to attack the actual cryptographic system.

share|improve this answer
1  
Nice! But the sole fact that it works actually scares me a bit; I hope Local Storage is not going to be abused just like the Flash Local Shared Objects, aka Flash-cookies, are being abused for tracking. (And just like third-party cookies were abused, and then got some protection.) –  Arjan Sep 12 '10 at 9:42
    
@Arjan - meh, in my opinion the entire problem is intractable. If you want to include third-party content on a website, you have to trust the third-parties in question. –  Kevin Montrose Sep 12 '10 at 10:01
    
True, but as a visitor it's the first-party website I need to trust in making the right judgement then. I'm not a PC, but IE's internet zone idea seems to allow for trusting first-party websites, which can then include whatever third-party content they wish? Sounds good, but I never saw (nor searched for) similar ideas in other browsers. As a result of my laziness: sorry to say I blocked third-party cookies and Flash LSOs (surely not perfect‌​). I really hope Local Storage does not get abused; I like what you built! :-) –  Arjan Sep 12 '10 at 11:45
1  
@Arjan - the onus is definitely on the first-party site, we're in complete agreement. –  Kevin Montrose Sep 12 '10 at 12:10
    
Thanks for the info, it's very insightful. Although I confess I'm not sure i understand the use of iFrames and how it fits it. I would appreciate more information around this if possible. thanks. –  Ash M Sep 13 '10 at 1:00
    
IFrames are necessary to get javascript running under a StackAuth's "context." Simply including the javascript (via a script tag, or similar) would cause all localStorage access to occur under the SE-site's domain. –  Kevin Montrose Sep 13 '10 at 2:17
    
Can third party websites check for the token's mere existence? –  badp Sep 13 '10 at 18:40
    
@badp - no. This scheme is not meant for third-parties in any way. Third party authentication will be part of some later API version, presumably. –  Kevin Montrose Sep 13 '10 at 18:46
    
@Kevin, I'm not asking if third parties are supposed to use it. I'm just asking if the mere existence of the token can be detected, say, by advertisement companies. –  badp Sep 13 '10 at 22:28
1  
@badp - no, only code originating from StackAuth can read the token. The token is also a random string, it doesn't contain any user identifying information; its used to lookup that information in a database. –  Kevin Montrose Sep 13 '10 at 22:56
    
Thank you for sharing this information with us. Many sites would prefer to keep these types of details secret (security through obscurity. right? RIGHT?) But this was a very interesting read and very informative from a development perspective. –  Matt Sep 23 '10 at 22:07
3  
@Matt - even if we wanted to use obscurity as part of our defense in depth (an approach which isn't entirely without merit... just nearly so, in my opinion), we run a site frequented by a talented pool of professional developers. It'd take a day, maybe two, before most of these details were reverse engineered by someone. Plus, we like talking about our clever hacks :) –  Kevin Montrose Sep 23 '10 at 23:02
    
@Kevin which postMessage are you referring to, the DOM one or the Windows API one? If the DOM one, how does the SE window send the credentials to the SE server? –  Falkayn Dec 21 '10 at 22:39
    
@Falkayn - developer.mozilla.org/en/DOM/window.postMessage <-that one. All communication with the servers is over standard HTTP. –  Kevin Montrose Dec 22 '10 at 22:19
    
@Kevin, thanks for that. So the one-time nonces are used to prevent the ability for an attacker to replay the login token to SE? –  Falkayn Dec 23 '10 at 1:09

They are using HTML 5 Local Storage. Jeff happened to publish a blog article just today, describing what happens behind the scenes:

share|improve this answer
1  
Sweet! Thanks. But can you also explain how HTML 5/local storage is not programming related? –  Mark Sep 12 '10 at 0:37
    
@Mark: I didn't vote for the migration. It fits on both sites in my opinion. Maybe those who voted for migration thought that you'd get better answers here :) –  Daniel Vassallo Sep 12 '10 at 3:38
1  
So... I read through both articles. I don't see a significant advantage of localStorage over cookies. We get 5 MB instead of 4 kB and a tiny bit of "added security" because the data is kept local and not sent with every request, and "speed" for the same reason. But, presumably, you need to send some login key when the user visits the page anyway, which is presumably encrypted and validated in either case. And speed... we're sending maybe 100 fewer bytes of data... which is all great and a step in the right direction, but its still only supported in the newer browsers. –  Mark Sep 12 '10 at 4:39
    
I'm also not sure why they opted to store everything as strings.. only to shortly after try to standardize some typed storages such as SQL or IndexedDB. But now I'm getting into the merits of localStorage. –  Mark Sep 12 '10 at 4:41
    
By "encrypted" I mean probably some kind of hash, but with localStorage or cookies, they could both be intercepted when it tries to log you in, no? Unless we're using SSL. You can't just SSL the "ajax" call that transmits the login info, can you? –  Mark Sep 12 '10 at 4:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .