Send custom data along with handshakeData in socket.io?

As a lot of comments have pointed out below the Socket.IO API changed in their 1.0 release. Authentication should now be done via a middleware function, see 'Authentication differences' @ http://socket.io/docs/migrating-from-0-9/#authentication-differences. I'll include my orginal answer for anyone stuck on <1.0 as the old docs seem to be gone.

1.0 and later:

Client Side:

//The query member of the options object is passed to the server on connection and parsed as a CGI style Querystring.
var socket = io("http://127.0.0.1:3000/", { query: "foo=bar" });

Server Side:

io.use(function(socket, next){
    console.log("Query: ", socket.handshake.query);
    // return the result of next() to accept the connection.
    if (socket.handshake.query.foo == "bar") {
        return next();
    }
    // call next() with an Error if you need to reject the connection.
    next(new Error('Authentication error'));
});

Pre 1.0

You can pass a query: param in the second argument to connect() on the client side which will be available on the server in the authorization method.

I've just been testing it. On the client I have:

var c = io.connect('http://127.0.0.1:3000/', { query: "foo=bar" });

On the server:

io.set('authorization', function (handshakeData, cb) {
    console.log('Auth: ', handshakeData.query);
    cb(null, true);
});

The output on the server then looked like:

:!node node_app/main.js
   info  - socket.io started
Auth:  { foo: 'bar', t: '1355859917678' }

Update

3.x and later

You can pass an authentication payload using the auth param as the second argument to connect() in the client side.

Client Side:

io.connect("http://127.0.0.1:3000/", {
    auth: {
      token: "AuthToken",
    },
  }),

In server side you can access it using socket.handshake.auth.token

Server Side:

io.use(function(socket, next){
    console.log(socket.handshake.auth.token)
    next()
});

This has now been changed in v1.0.0. See the migration docs

basically,

io.set('authorization', function (handshakeData, callback) {
  // make sure the handshake data looks good
  callback(null, true); // error first, 'authorized' boolean second 
});

becomes :

  io.use(function(socket, next) {
  var handshakeData = socket.request;
  // make sure the handshake data looks good as before
  // if error do this:
    // next(new Error('not authorized');
  // else just call next
  next();
});