Mqtt.js: Add an urlSigner (func) option to connect to pass to the ws streambuilder

Created on 12 Feb 2017  路  8Comments  路  Source: mqttjs/MQTT.js

For AWS IoT wss connections urls require Sigv4 signing. These urls seemingly expire, so eventually reconnect doesn't work and you need a fresh signature.

You can see here usage of an old version of mqtt.js: https://github.com/aws/aws-iot-device-sdk-js/blob/master/device/index.js#L502-L521

I'm using mqtt.js 2.x directly and my own url signer implementation.

I will possibly get around to a pull request but first would like to see how do people feel about adding an urlSigner function to the connection options, passed along to the stream builder[s]?

Most helpful comment

Async version would definitely help as the link is normally generated on the server side rather than client.

All 8 comments

I'm more keen on passing a function to connect that will return the URL (or call a callback with an URL).

If that simplifies things for SDKs, then let's go for it.

Something like:

interface Options {}
class MqttClient {}
type urlCallback = (err: Error, url: string) => void
type asyncUrlBuilder (cb: urlCallback) => void
type urlBuilder = () => string | asyncUrlBuilder
type url = string | urlBuilder 
function connect(url : url, options: Options) => MqttClient

?

/**
 * connect - connect to an MQTT broker.
 *
 * @param {String} [brokerUrl] - url of the broker, optional
 * @param {Object} opts - see MqttClient#constructor
 */
function connect (brokerUrl, opts) {

Hrmmm

IMO it would probably be simplest to just add a function (through the opts) that synchronously transforms the url passed to websocket() each time, here:
https://github.com/mqttjs/MQTT.js/blob/master/lib/connect/ws.js#L99
and here:
https://github.com/mqttjs/MQTT.js/blob/master/lib/connect/ws.js#L45

How would folks feel about a PR adding an async version of this function, so that URLs could be signed remotely? For AWS ioT in particular, this would allow you to ensure an approved clientId and eliminate the need for a local crypto implementation.

@jed if it does not add too much complexity, sure!

Async version would definitely help as the link is normally generated on the server side rather than client.

I managed to code around the need for an async transformWsUrl

Use the error event

client.on('error', (err) => {
  // error code 5, Connection refused: Not authorized
  if (err.code === 5) {
    // token may have expired so try to get a new one
    // insert http get here to grab new token
    // then set a token variable that is accessible in the scope of your transformWsUrl function
  }
}
Was this page helpful?
0 / 5 - 0 ratings