Friday, February 19, 2010

Coupon etiquette?

What's the 'correct' social etiquette about using restaurant coupons purchased online (such as those from restaurant.com or groupon.com) when you go out in a group and split the check?

For coupons you get in the mail, or basically free stuff, I assume common etiquette is to offer the coupon to the group to use and split the remainder. Does it work the same way when you've bought, say, a $50 coupon for $25 (i.e. you use the coupon to cover $25 off your tab and offer the discount value to the group)? Do you use the entire $50 to cover just your tab? Or maybe simply not using the coupon when dining as a group is the right way to go?

Tuesday, February 9, 2010

Hey Google Buzz, I don't email my friends anymore

I just saw the presentation from Google about Google Buzz. The quick summary of the announcements - creating a social network using my email contacts and emailing history as the source of my social graph, and using rich geo-tagged status messages (buzz-es) to keep it updated. It comes with rich mobile apps to help this take off. They also promised enterprise versions of Buzz.

Buzz sounds pretty exciting. Some of the geo-tagged updates sounds really slick. My first reaction - this is going to be 'public follow' thing more than a 'follow my friends' things. Because emailing my friends is like, so 2007!

Fact is, I don't email my closest friends/family anymore. I either IM them, post on their Facebook page, send them SMS or call them. Email is more for work type, non-personal stuff. Having said that, it's important to note that Google does have GTalk and Google Voice so I hope they weigh activity from GTalk and Google Voice higher than GMail activity when figuring out who I must 'auto-follow'.

Time for someone to write a Buzz-to-Facebook cross poster. :)

Monday, January 25, 2010

Test cases for basic Facebook Connect integration

I recently spent a couple of days adding some basic Facebook Connect functionality to an existing site with it's own Login/Auth system. The process isn't too hard and there are several examples and even a nice tutorial which shows you exactly how to hook this up.

The tutorials and the Facebook developer wiki to a good job of getting you on the right path and putting up a quick working implementation. However, there are several subtleties that need to be addressed, depending on the requirements of the existing site. I didn't really find a good compilation of these 'test cases' anywhere. Facebook's own documentation probably references several of these but they're scattered all over their wiki page and are very easy to miss if your primary focus is getting this stuff up and running quickly.

This blog post is my attempt to compile of list of things you need to think about when adding Facebook Connect support for sign up/login or linked accounts on an existing site with its own authorization system. Here are a few characteristics (pretty standard) of the existing site:
  • Authentication using a username/email address and password
  • Cookies to help keep users logged in
  • Accounts keyed by email address (i.e. 1:1 mapping between accounts and email address)
  • Ability to reset accounts by having a temp password send to user's email address
  • Fully ajax navigation (which complicates matter a little bit)
  • Logout functionality which clears up cookies
The goals for the Facebook Connect integration are pretty simple:
  • New User Sign Up without needing to create a site-specific password (email address needed)
  • Ability for existing users to link with their Facebook account
  • 1:1 mapping between accounts on your site and Facebook accounts
  • Single sign-on experience
Let's call the existing site YouFace. I won't go into how to get stuff hooked up or explaining how to implement this - it's not too complicated and there's a bunch of information online for it. Instead, treat this as a list of a few things you probably want to test when you're done. There shouldn't really be anything ground breaking here - this was just a convenient way for me to build a list of things to test on my own site. Some of these are handled by the Facebook Connect client library, while some need your application to do the right thing. Please comment if I've missed any cases or if some just appear wrong - I would love to fix my site!
  • Sign Up should fail if the user denies permission to the app (category: sign up)

  • Since we need access to an email address, Sign Up should fail if the user provides publish permission but denies email permission (category: sign up)

  • If the user provides an email address that already exists in your system, fail Sign Up. Make sure no YouFace backend tables are modified (category: sign up, 1:1 mapping) PS - when this happens, I didn't find a way for you to de-authorize YouFace on the Facebook user's behalf. The user must manually do this if they wish you use the same account but provide a different email address.

  • Accounts created using Facebook Connect should not be able to login using YouFace's default email/password login system (category: sign in, account security). PS: Since YouFace accounts require a password and those created using Facebook Connect don't, make sure to insert a random password hash into your table to avoid silly errors

  • Accounts created using YouFace should be able to sign in without requiring to be signed into Facebook, even if when a link to a Facebook accounts exists (category: sign in)

  • Attempting to Sign Up with a Facebook account that's already linked and authorized should result in the Sign In experience (category: sign up, sign in)

  • Attempting to Sign In with a Facebook account that YouFace hasn't seen before should lead to the Sign Up experience, i.e. create a new account (category: sign up, sign in)

  • Linking a Facebook account with an existing YouFace account should add the email address from Facebook to the list of 'used addresses' in the YouFace system (category: linking, 1:1 mapping)

  • When a Facebook linked account de-authorizes YouFace, your system should record this action and change state as needed (category: authorization)

  • Linking a YouFace account with a Facebook account that's already been linked to some other account in your system should be denied (category: linking, 1:1 mapping, authorization)

  • Users with linked accounts can continue to sign in using their YouFace credentials even after they de-authorize YouFace from their Facebook account (category: linking, authorization)

  • Linking a Facebook account different from one you originally linked to an existing YouFace account should be denied. This can happen when an existing user links a YouFace account to Foo@FB, de-authorizes the app and then tries to link Bar@FB to that account (category: linking, 1:1 mapping, authorization)

  • A user who Signed Up using Facebook Connect should not be allowed to link their account to another Facebook account (category: sign up, 1:1 mapping)

  • Attempting to Sign In or Sign Up with a Facebook account that YouFace has seen, but one that has currently not authorized the YouFace app (maybe the user revoked authorization) should ask to re-authorize before proceeding. It must log the user into the original YouFace account linked with that Facebook account, i.e. no new account should be created. If that account was originally created using Facebook Connect, the primary email address should be updated to reflect the user's current Facebook contact email address else the primary email address should not be changed from what the user provided YouFace when they signed up (category: sign in, 1:1 mapping, reauthorization)

  • If a user with a linked account is logged into Facebook, they should be signed into YouFace directly (category: single sign in)

  • Users who signed into YouFace with Facebook Connect should be logged out of Facebook if they log out of YouFace (category: single sign out)

  • Users who signed into YouFace with Facebook Connect should be logged out of YouFace if they log out of Facebook (category: single sign out)

  • Users with linked accounts who signed into YouFace directly (not using Facebook Connect) should continue to remain signed in, regardless of whether they're were originally signed into Facebook, when they sign out of Facebook (category: sign in, sign out)

  • Users who created their account using Facebook Connect should not be allowed to reset passwords or have temporary passwords sent to their email addresses (category: account security)

  • This is a kinda convoluted. Users Foo and Bar both have YouFace accounts linked to Facebook. Bar is logged into YouFace with his YouFace account, and Foo is logged into Facebook, in the same instance of the browser (Bar logged in first). When Bar logs out of YouFace, Foo should not get logged out of Facebook (category: single sign out, multiple accounts ). PS: YouFace's Connect library is going to pick up a valid Facebook ID but it's that of Foo, not Bar. So you need to do more than just client-side detection of whether someone's logged into Facebook.

Wednesday, December 23, 2009

Browser history navigation bug in Chrome and Safari

I've been seeing some odd behavior in Chrome - occasionally browser history would get hosed pretty badly. When I noticed the same issue navigating the website I'm working on, I ended up spending a bunch of time trying to get to the bottom of the issue. Initially I suspected it was something wrong with the site, but I was eventually able to create a stand-alone repro for Chrome (v3 and v4) as well as for Safari (v4). I suspect this might be a WebKit thing, which both browsers share, but I don't know enough to be certain.

The problem seems to occur when you spend time moving around fully ajax sites that contain one or more iframes (I've seen this on GMail as well). In my case I worked around this issue by not using iframes but I imagine that's not always possible. Anyways, this is now Chromium bug 30693.

Friday, October 9, 2009

XSRF/CSRF Vulnerability Explained in Non-Geek Speak

I recently explained what cross-site request forgery (CSRF/XSRF) is to a friend who isn't a programmer/CS person and I was pretty amazed at how quickly he understood the implications of not protecting against such attacks. With the proliferation of social interactions on the web now, such attacks can be pretty damaging to consumers of new media and e-commerce sites.

The Wikipedia article about CSRF does a pretty good job of explaining the issue - most people familiar with web development should be able to understand it easily. Basically, this attack lets legitimate unsuspecting users submit changes to a site they routinely interact with, but without their knowledge. CSRF attacks leverage your own browser and the trust you associate with it to perform potentially damaging actions on your behalf.

Here's an example of what such an attack might look like. Let's assume that Facebook wasn't protected against such attacks, for the purpose of this illustration. In reality, I'm sure Facebook engineers have done a good job of making sure this can't really ever happen. That's not true of every site out there, though.

When you sign into Facebook, you have the option of remaining signed in. To do this, sites like Facebook set a browser cookie which identifies you to their servers. This is great because it lets you visit the site frequently and navigate the site without needing to enter your password every time. Browsers are good about securing your cookie - they make sure that no other site besides Facebook can see this cookie, so it's not possible for the author of www.hacker.com to steal your cookie and present it to Facebook and then impersonate you. However, each time you go to any URL that contains www.facebook.com, the browser diligently sends over all cookies associated with Facebook, because the receiver of those cookies is www.facebook.com.

Once on Facebook, you do things like update your status or write on a friend's wall. When you do that, the browser sends your new status update to Facebook along with the cookies. By inspecting the cookie, Facebook is able to validate that it is indeed you trying to update your own status, so it proceeds to allow the action. Under the covers, your browser is sending over two pieces of information - some data (your status update text, in this case) and the cookies. The browser was triggered to do this by you clicking the "Submit" button. This sounds pretty straightforward so far.

Now imagine you're browsing the web and land on this page that talks about world hunger and how you can help the cause by simply clicking a "Help the Children" button. With only altruistic intentions, you click on the button. Nothing visible happens, or maybe a "Thank you!" label replaces that button. Then you simply move on to the next thing you were going to do. Suddenly, you start receiving email notifications about friends responding to your latest status update on Facebook, except you never posted any update. You visit Facebook and sure enough your status now says "I am a loser!", updated 2 minutes ago. Huh?! You didn't set that status. You panic - maybe someone hacked your account? Or someone guessed your password? What's going on?

What really happened was that the world hunger website you were on was written by a malicious attacker, and when you clicked the "Help the Children" button that website didn't really contribute 10 cents to UNICEF, but instead told your browser to send a new status update with the text "I am a loser!" to www.facebook.com. This site couldn't access your cookies directly, so the browser didn't do anything bad and stuck to its promise of not letting anyone else see cookies that shouldn't be visible to them. Remember, the attacker never looked at your cookie at all while any of this happened. However, when the attacker asked the browser to send data to www.facebook.com, the browser added the Facebook cookies to the request. So now Facebook looks at the cookies and the data, thinks that it is indeed you and goes on to update your status. Boom!

So what went wrong here? The browser didn't do anything bad - it did exactly what it's supposed to. It hid your Facebook cookies from everyone except Facebook and it sent data that submitting the "Help the Children" button asked it to send. You didn't do anything bad - you simply clicked on a link that was meant to help needy kids. You did have cookies enabled (default for most browsers) and decided to check that "Log in automatically" option, but those seem like reasonable actions.

The flaw here is with the website you trusted - Facebook, in this example. Sites like Facebook that rely on cookies to identify and authorize user actions need to do more things than just validate your cookie when data is presented to the site on your behalf. They need to make sure that place from which the data was sent was 'good', or that a malicious author cannot create data the same way that www.facebook.com can. They need to make sure that when you update your status, the data contain more than just your new status text - there must be some kind of secret information in there that can only be generated by Facebook, and this secret must be different for each Facebook user. They can even control how long cookies and secrets remain valid, and have ways to periodically require users to sign in and generate new unique secrets for users.

Of course, this is just a silly example. I'm sure Facebook is perfectly adept and handling such attacks. However, a vulnerability like this could impact everything from online review sites to banking and e-commerce sites. It's always good to be aware of things that could go wrong online - the Internet is definitely not as safe as you might think it is.


Wednesday, September 30, 2009

So, how was your date?

A funny exchange at work today...

I designed this piece of UI putting together all my newly-acquired Javascript and Paint.NET (a free Photoshop-like tool) skills, and it looked pretty fancy for what I thought I was going to end up with. After playing with it for a bit my co-worker responded: "Thanks for putting that together Viraj - I really like the concept. I can't wait to see what a designer can do with it".

Lol... this sounds a lot like the "She's got a great personality..." line of the dating scene.

Like I said previously, UI design is so much harder than I thought it was!

Friday, September 18, 2009

Fix for slow Firefox/Chrome connects to localhost

While doing some recent testing I noticed that Chrome(v3) and Firefox(v3.5) are both very slow to connect to http://localhost on Windows 7 - both take ~1 second just to connect.

I initially suspected something was wrong with the webserver on localhost, but once I validated that wasn't it, I found some blog posts about others who had noticed this in Vista and XP. Essentially, disabling ipv6 takes care of the slowness.

However, to fix the issue, have the client use http://127.0.0.1 instead of http://localhost - it bypasses ipv6 without you needing to mess with browser configuration.