Server authentication using Faye on Node.js

So I am extremely new to node.js, and faye - so I think this is pretty basic, but I'm not sure what I should be asking.

I have this setup for my faye server, running on node jitsu:

var http = require('http'),
    faye = require('faye');

var bayeux = new faye.NodeAdapter({mount: '/faye', timeout: 45});

// Handle non-Bayeux requests
var server = http.createServer(function(request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.write('Hello, non-Bayeux request');
  response.end();
});
bayeux.attach(server);
server.listen(8000);

var fayeToken = "myToken";

var serverAuth = {
  incoming: function(message, callback) {
    // Add an error if the tokens don't match
    if (fayeToken !== message.ext.auth_token)
        message.error = 'Invalid auth token';

      // Call the server back now we're done
      callback(message);
  }
};

bayeux.addExtension(serverAuth);

Then I have a rails app that connects to it.

Before I added the serverAuth stuff, it was working fine.

When I curl like so:

curl http://myapp.jit.su/faye -d 'message={"channel":"/alerts", "data":"hello", "ext":{"auth_token":"myToken"}}'

I get a success message.

In my JS file on the rails app I have:

$(function() {
    //FAYE CLIENT
    var faye = new Faye.Client('http://myapp.jit.su/faye');
    faye.setHeader('ext.auth_token', 'myToken');
    faye.subscribe("/alerts", function(data) {
        alert(data);
    });
});

Now I get a bad request 400 error when the rails app loads for the faye script.

The params being sent are specifically:

[{"channel":"/meta/handshake","version":"1.0","supportedConnectionTypes":["callback-polling"],"id":"1"}]

So it seems as though the header param that I'm setting isn't being sent in this "meta" handshake that faye does.

Before I had this server authentication in, it worked just fine, and I could curl messages into the app. No dice now.

Any ideas where I'm going wrong?

Thanks!

For future reference:

I had to make sure its not doing a meta call:

var serverAuth = {
  incoming: function(message, callback) {
    // Let non-subscribe messages through
        if (message.channel.indexOf("/meta/") !== 0){
            if (fayeToken !== message.ext.auth_token){
                message.error = 'Invalid auth token';
            }
        }   
      callback(message);
  }
};

There's two problems here that I can see here. First, your extension will fail if the message does not have an ext field. You should check for it before checking message.ext.auth_token:

var serverAuth = {
    incoming: function(message, callback) {
    // Let non-subscribe messages through
        if (message.channel.indexOf("/meta/") !== 0){
            if (!message.ext || fayeToken !== message.ext.auth_token){
                message.error = 'Invalid auth token';
            }
        }   
        callback(message);
    }
};

I'm also not sure what you're trying to authenticate. if (message.channel.indexOf("/meta/") !== 0) will match any non-meta message, i.e. all messages sent with publish() (meta messages are used for handshaking, polling, (un)subscribing, and disconnecting). This means anyone can publish messages, but only the server can subscribe to any channels.

Second, ext is part of the messages themselves, whereas setHeader() is used to set HTTP headers, i.e. it's part of the transport layer. You should use an extension to add ext to messages:

client.addExtension({
    outgoing: function(message, callback) {
        message.ext = message.ext || {};
        message.ext.auth_token = THE_TOKEN;
        callback(message);
    }
});