Adding connection headers on DDP

Is it possible to modify the connection headers on DDP?
I’m considering ways to allow auxilliary applications to interact with my private network.
The most obvious way is to add an API key.

I want nginx to check for the API key in the headers and return a 403 if there is a problem.
But it isn’t clear if/how this can be done with DDP.

I’m asking in relation to meteor and 3rd party aps.
e.g.

  1. Can I do it with Meteor
  2. If I use a DDP connection client for C++/Java/whatever (I’m ok modifying it if I need to) Will I be able to add the header?
1 Like

Okay, I have stumbled upon this issue by myself today. Short answer: you can add ‘some white-listed headers’. The complete list can be found in SockJS source code (though even they do not explain that in their documentation :frowning:).

Here is the link to the source: https://github.com/sockjs/sockjs-node/blob/02c4dcd6ff7112834cad50fae236335fb407208f/src/transport.coffee

And here is the list of the supported headers:
['referer', 'x-client-ip', 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-port', 'x-cluster-client-ip', 'via', 'x-real-ip', 'x-forwarded-proto', 'x-ssl', 'dnt', 'host', 'user-agent', 'accept-language']

You just add the headers in the second parameter in DDP.connect function (it also not documented on Meteor side, but is visible in source code: https://github.com/meteor/meteor/blob/master/packages/ddp-client/common/livedata_connection.js
), for example:

DDP.connect('http://localhost:3000',{
  headers: {
    "User-Agent": 'my-white-listed-string'
  }
})

and then on the host server see it like this:

Meteor.onConnection(function (connection) {
  console.log('User-Agent', connection.httpHeaders['user-agent']);
})

The SockJS guys also explain and discuss why they do not support Authorization header here:
https://github.com/sockjs/sockjs-client/issues/196 and the short answer is: Authorization header is threat to security and thus authorization “should occur over the SockJS channel”.

BUT. Here are 2 questions to Meteor DDP experts:

  1. Please share your opinion on what kind of security threat can it be, when on every connection I would just pass an api key and validate it (and when it is not valid - just close the connection)? Since I am just connecting Meteor server to Meteor server, it has nothing to do with the mentioned iFrame they are using under the hood…

  2. Can there be any issue if I pass my api key using the white listed ‘User-Agent’ header, for example like “User-Agent”: “auth:some-super-long-api-key”, and then firstly validate user agents quickly by the first 4 letters and then if it is valid, will perform full api key validation?

5 Likes

Just one more note to this to be aware.

If you are trying to connect 2 servers in dev environment, and if your ServerA is, say, on port 3000, keep in mind that the 3001 port is taken by default with your ServerA mongo connection. So you’d better have ServerB in a port, say 4000 (meteor run --port 4000). This would save you few hours figuring out why you are having this error trying to connect to 3001 port:

stream error Error during WebSocket handshake: Unexpected response code: 200

And also, to Meteor team - please white-list more headers or add an authentication property/option to DDP.connect. Not always you can have a privilege of having both servers working within a secured private network.

Honestly, it is a shame that after 6 years the only valid way of authenticating DDP server to server connection is to send a token with “User-Agent” header. :slight_smile: