Facebook, OpenID and Decrypting SSL
I was excited to see Facebook (FB) supporting login via OpenID (FB is a relying party), and I decided to give it a whirl. Here I list the results of my investigation, which describe the odd use of OpenID, as well as my wire level analysis which I hope you find informative. This post doesn't go into details of how OpenID works, if you're interested in that leave a comment and I'll put up such a post.
FB uses OpenID in a way I've never seen before. In the "common" OpenID login model, you get a login page that shows you some sort of login via OpenID buttons. When you go to the FB login page there is no login via OpenID. This confused me, but I went to my FB account settings and linked my google account to my FB account. (Attempts to link my MyOpenID account failed with a strange error message).
After some trial and error I realized that if I was logged into my Google account and went to the FB page than I'd automatically get logged into FB.
Debugging SSL via Charles
I needed to look at the network layer to see what is going on. Some of you may want to investigate this with tshark, but much of the traffic runs over SSL, since we don't have the server certs that's a dead end. Instead you should fire up Charles, an http(s) debugging proxy. Charles can sit in the middle of your SSL connections, and relay SSL traffic by presenting ‘untrusted certs’. Visually it looks like this:
How Facebook OpenID login works at a high level:
- Facebook login page contains javascript that tells your browser to login to Yahoo and Google via OpenID
- Your browser tries to connect to Yahoo and Google OpenID Endpoints, which post results back to FB
- If the login via OpenID succeeds, and you have a linked account you get logged into FB.
- If the request fails or there is no linked account you see nothing.
The Facebook OpenID approach:
If you’re logged into your Google account, and then go to the FB page, you’ll be automatically logged into FB, otherwise nothing happens. This is by design as mentioned here.
This is an interesting implementation of login via OpenID. It has the following advantages:
- It’s immune to phishing
- It requires no UI when you’re logged into your OpenID provider
At the same time there are some big disadvantages:
- There is a privacy leak as all OpenID providers supported by FB now know you’re trying to access FB and at what frequency and from what client
- FB needs to connect to every OpenID provider that exists on login.
- FB doesn’t allow you to specify which account you want to use to login if you have multiple.
- You can’t link your FB account to OpenID by logging into OpenID
- It’s hard to discover login is failing because you aren’t signed into an OpenID account.
I look forward to seeing how FB moves this forward.
How Facebook OpenID login works at a protocol level:
This is probably too geeky for most but I find it interesting so I’ll share it. Comment if you’d like to see more of this sort of analysis.
The first column is the return code 200 is success, 302 is a redirect. Second column is the DNS name, and third column is truncated request.
1) Facebook login page contains javascript that tells your browser to login to Yahoo and Google via OpenID
// Connect to FB
200 GET www.facebook.com
// JavaScript connects to FB Analytics system telling them what we're trying.
200 GET pixel.facebook.com /ajax/openid/metrics.php?metric=requestSent&immediate=true&context=background_login&openid_url=http%3A%2F%2Fyahoo.com%2F&asyncSignal=779
200 GET pixel.facebook.com /ajax/openid/metrics.php?metric=requestSent&immediate=true&context=background_login&openid_url=http%3A%2F%2Fgmail.com&asyncSignal=9380
// 2) Javascript tries to connect to Yahoo and Google OpenID Endpoints, which post results to: www.facebook.com/openeid/receiver
// 2.1) HTTPS connection to Google OpenID
302 GET www.google.com /accounts/o8/ud?openid.claimed_id=…
// 2.2) HTTPS connection to Yahoo OpenID
302 GET open.login.yahooapis.com /openid/op/auth?openid.claimed_id=…
// 2.3) Yahoo OpenID telling FB it failed.
302 GET www.facebook.com /openid/receiver.php?provider_id=1923581983856&openid.mode=setup_needed&…
// 2.4) Google OpenID telling FB it succeeded.
302 GET www.facebook.com /openid/receiver.php?provider_id=1010459756371&…openid.sig=…
// FB telling itself the Yahoo login failed (this gives FB the chance to add new paramters server side, which it does)
200 GET www.facebook.com /openid/receiver.php?provider_id=1923581983856&…
// FB recording stats that the yahoo login failed.
200 GET pixel.facebook.com /ajax/openid/metrics.php?metric=requestCanceled&immediate=true&context=background_login&openid_url=http%3A%2F%2Fyahoo.com…
// FB telling itself the Google Login Succeeded (this gives FB the chance to add new paramters server side, which it does)
200 GET www.facebook.com /openid/receiver.php?provider_id=1010459756371 …
// 3. If the login via OpenID succeeds, and you have a linked account you get logged into FB. (FB Logging in)
302 POST www.facebook.com /login.php
200 GET www.facebook.com /
The actual request if you’re feeling really geeky:
// More Details 2.1) HTTPS connection to Google OpenID
openid.claimed_id http://specs.openid.net/auth/2.0/identifier_select
openid.ext0.mode fetch_request
openid.ext0.required email,first_name,last_name,country,language,dob
openid.ext0.type.country http://axschema.org/contact/country/home
openid.ext0.type.dob http://axschema.org/birthDate
openid.ext0.type.email http://axschema.org/contact/email
openid.ext0.type.first_name http://axschema.org/namePerson/first
openid.ext0.type.language http://axschema.org/pref/language
openid.ext0.type.last_name http://axschema.org/namePerson/last
openid.identity http://specs.openid.net/auth/2.0/identifier_select
openid.mode checkid_immediate
openid.ns http://specs.openid.net/auth/2.0
openid.ns.ext0 http://openid.net/srv/ax/1.0
openid.ns.oauth http://specs.openid.net/extensions/oauth/1.0
openid.ns.ui http://specs.openid.net/extensions/ui/1.0
openid.oauth.consumer www.facebook.com
openid.oauth.scope http://www.google.com/m8/feeds/contacts/
openid.realm https://www.facebook.com/
openid.return_to https://www.facebook.com/openid/receiver.php?provider_id=1010459756371&protocol=http&context=background_login&request_id=1
openid.ui.icon true
openid.ui.mode popup
// More Details 2.4) Google OpenID telling FB it succeeded.
provider_id 1010459756371
protocol http
context background_login
request_id 1
openid.ns http://specs.openid.net/auth/2.0
openid.mode id_res
openid.op_endpoint https://www.google.com/accounts/o8/ud
openid.response_nonce 2010-10-14T06:07:08ZPY_ztwISRBSIzA
openid.return_to https://www.facebook.com/openid/receiver.php?provider_id=1010459756371&protocol=http&context=background_login&request_id=1
openid.assoc_handle ...
openid.signed op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle,ns.ext1,ns.ext2,ext1.mode,ext1.type.first_name,ext1.value.first_name,ext1.type.email,ext1.value.email,ext1.type.language,ext1.value.language,ext1.type.last_name,ext1.value.last_name,ext2.scope,ext2.request_token
openid.sig oCFFt53s1j4rD7kGOE8x1ycZMfU=
openid.identity https://www.google.com/accounts/o8/id?id=...
openid.claimed_id https://www.google.com/accounts/o8/id?id=...
openid.ns.ext1 http://openid.net/srv/ax/1.0
openid.ext1.mode fetch_response
openid.ext1.type.first_name http://axschema.org/namePerson/first
openid.ext1.value.first_name Igor
openid.ext1.type.email http://axschema.org/contact/email
openid.ext1.value.email ...
openid.ext1.type.language http://axschema.org/pref/language
openid.ext1.value.language en
openid.ext1.type.last_name http://axschema.org/namePerson/last
openid.ext1.value.last_name ...
openid.ns.ext2 http://specs.openid.net/extensions/oauth/1.0
openid.ext2.scope http://www.google.com/m8/feeds/contacts/
openid.ext2.request_token 4/bv0-X57lya6ESvrvYG3pQiAGuSzn
openid.ns.ext3 http://specs.openid.net/extensions/ui/1.0
openid.ext3.mode popup
Comments