asterisk / node-ari-client

Node.js client for ARI. This library is best effort with limited support.
Other
250 stars 98 forks source link

Cryptic error when ARI user password has special characters #76

Closed glyphCezilleSantillan closed 7 years ago

glyphCezilleSantillan commented 7 years ago

When calling ari.start(), I encountered a mysterious error that left the following trace:

Unhandled rejection Error: undefined
    at Object.ensureErrorObject (/home/<user>/src/<ari_app>/node_modules/bluebird/js/main/util.js:261:20)
    at Promise._rejectCallback (/home/<user>/src/<ari_app>/node_modules/bluebird/js/main/promise.js:472:22)
    at /home/<user>/src/<ari_app>/node_modules/bluebird/js/main/promise.js:489:17
    at /home/<user>/src/<ari_app>/node_modules/ari-client/lib/client.js:327:11
    at /home/<user>/src/<ari_app>/node_modules/underscore/underscore.js:890:21
    at reconnect (/home/<user>/src/<ari_app>/node_modules/ari-client/lib/client.js:526:9)
    at WebSocket.processError (/home/<user>/src/<ari_app>/node_modules/ari-client/lib/client.js:509:7)
    at emitOne (events.js:77:13)
    at WebSocket.emit (events.js:169:7)
    at ClientRequest.response (/home/<user>/src/<ari_app>/node_modules/ws/lib/WebSocket.js:721:12)
    at ClientRequest.g (events.js:260:16)
    at emitOne (events.js:77:13)
    at ClientRequest.emit (events.js:169:7)
    at HTTPParser.parserOnIncomingClient (_http_client.js:433:21)
    at HTTPParser.parserOnHeadersComplete (_http_common.js:103:23)
    at Socket.socketOnData (_http_client.js:322:20)
    at emitOne (events.js:77:13)
    at Socket.emit (events.js:169:7)
    at readableAddChunk (_stream_readable.js:153:18)
    at Socket.Readable.push (_stream_readable.js:111:10)
    at TCP.onread (net.js:537:20)

Suspiciously, it occurred about a minute after connecting. Looking around, it turned out that my ARI user had some special characters (+) that weren't being escaped. When creating the websocket url, it added my user as is:

var wsUrl = util.format(
    '%s://%s/ari/events?app=%s&api_key=%s:%s',
    (self._connection.protocol === 'https:' ? 'wss' : 'ws'),
    self._connection.host,
    applications,
    self._connection.user,     // <-- may be unsafe
    self._connection.pass
);

It resulted in 401s that didn't bubble up well, and finally culminated in the above error.

Is this a bug? Or should I be url-encoding my own usernames/passwords...or should I simply avoid special characters altogether?

chadxz commented 7 years ago

If it is indeed due to the need to urlencode your username then that should be handled by the library. Can you try testing with a plain username and password to see if that fixes it?

On Dec 16, 2016 3:23 AM, "Cezille Santillan" notifications@github.com wrote:

When calling ari.start(), I encountered a mysterious error that left the following trace:

Unhandled rejection Error: undefined at Object.ensureErrorObject (/home//src//node_modules/bluebird/js/main/util.js:261:20) at Promise._rejectCallback (/home//src//node_modules/bluebird/js/main/promise.js:472:22) at /home//src//node_modules/bluebird/js/main/promise.js:489:17 at /home//src//node_modules/ari-client/lib/client.js:327:11 at /home//src//node_modules/underscore/underscore.js:890:21 at reconnect (/home//src//node_modules/ari-client/lib/client.js:526:9) at WebSocket.processError (/home//src//node_modules/ari-client/lib/client.js:509:7) at emitOne (events.js:77:13) at WebSocket.emit (events.js:169:7) at ClientRequest.response (/home//src//node_modules/ws/lib/WebSocket.js:721:12) at ClientRequest.g (events.js:260:16) at emitOne (events.js:77:13) at ClientRequest.emit (events.js:169:7) at HTTPParser.parserOnIncomingClient (_http_client.js:433:21) at HTTPParser.parserOnHeadersComplete (_http_common.js:103:23) at Socket.socketOnData (_http_client.js:322:20) at emitOne (events.js:77:13) at Socket.emit (events.js:169:7) at readableAddChunk (_stream_readable.js:153:18) at Socket.Readable.push (_stream_readable.js:111:10) at TCP.onread (net.js:537:20)

Suspiciously, it occurred about a minute after connecting. Looking around, it turned out that my ARI user had some special characters (+) that weren't being escaped. When creating the websocket url, it added my user as is:

var wsUrl = util.format( '%s://%s/ari/events?app=%s&api_key=%s:%s', (self._connection.protocol === 'https:' ? 'wss' : 'ws'), self._connection.host, applications, self._connection.user, // <-- may be unsafe self._connection.pass );

It resulted in 401s that didn't bubble up well, and finally culminated in the above error.

Is this a bug? Or should I be url-encoding my own usernames/passwords...or should I simply avoid special characters altogether?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/asterisk/node-ari-client/issues/76, or mute the thread https://github.com/notifications/unsubscribe-auth/AAS34-OSteoYfFhXR9HdRk0Qiupez7ldks5rIliIgaJpZM4LO_dl .

chadxz commented 7 years ago

And by "should be handled" I mean that it should be the library's responsibility to do that, so if that's actually the case then we should fix it here

On Dec 16, 2016 6:36 AM, "Chad McElligott" chad.mcelligott@gmail.com wrote:

If it is indeed due to the need to urlencode your username then that should be handled by the library. Can you try testing with a plain username and password to see if that fixes it?

On Dec 16, 2016 3:23 AM, "Cezille Santillan" notifications@github.com wrote:

When calling ari.start(), I encountered a mysterious error that left the following trace:

Unhandled rejection Error: undefined at Object.ensureErrorObject (/home//src//node_modules/bluebird/js/main/util.js:261:20) at Promise._rejectCallback (/home//src//node_modules/bluebird/js/main/promise.js:472:22) at /home//src//node_modules/bluebird/js/main/promise.js:489:17 at /home//src//node_modules/ari-client/lib/client.js:327:11 at /home//src//node_modules/underscore/underscore.js:890:21 at reconnect (/home//src//node_modules/ari-client/lib/client.js:526:9) at WebSocket.processError (/home//src//node_modules/ari-client/lib/client.js:509:7) at emitOne (events.js:77:13) at WebSocket.emit (events.js:169:7) at ClientRequest.response (/home//src//node_modules/ws/lib/WebSocket.js:721:12) at ClientRequest.g (events.js:260:16) at emitOne (events.js:77:13) at ClientRequest.emit (events.js:169:7) at HTTPParser.parserOnIncomingClient (_http_client.js:433:21) at HTTPParser.parserOnHeadersComplete (_http_common.js:103:23) at Socket.socketOnData (_http_client.js:322:20) at emitOne (events.js:77:13) at Socket.emit (events.js:169:7) at readableAddChunk (_stream_readable.js:153:18) at Socket.Readable.push (_stream_readable.js:111:10) at TCP.onread (net.js:537:20)

Suspiciously, it occurred about a minute after connecting. Looking around, it turned out that my ARI user had some special characters (+) that weren't being escaped. When creating the websocket url, it added my user as is:

var wsUrl = util.format( '%s://%s/ari/events?app=%s&api_key=%s:%s', (self._connection.protocol === 'https:' ? 'wss' : 'ws'), self._connection.host, applications, self._connection.user, // <-- may be unsafe self._connection.pass );

It resulted in 401s that didn't bubble up well, and finally culminated in the above error.

Is this a bug? Or should I be url-encoding my own usernames/passwords...or should I simply avoid special characters altogether?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/asterisk/node-ari-client/issues/76, or mute the thread https://github.com/notifications/unsubscribe-auth/AAS34-OSteoYfFhXR9HdRk0Qiupez7ldks5rIliIgaJpZM4LO_dl .

samuelg commented 7 years ago

Yeah, that's on us, sorry about that.

glyphCezilleSantillan commented 7 years ago

@chadxz To illustrate, here's couple of sample users in ari.conf:

[normal]

type=user
password=nothingspecial

[special]

type=user
password=s3cre+

Assume we have a dialplan that launches a stasis app "some_app", then in node:

ari.connect('http://127.0.0.1:8088', 'normal', 'nothingspecial').then(function (client) {
    client.start("some_app");
    // ... rest of app code
});

The code proceeds quickly and does as expected.

However,

ari.connect('http://127.0.0.1:8088', 'special', 's3cre+').then(function (client) {
    client.start("some_app").catch(function (err) {
        console.log(err);         // prints the error in first post (Error: undefined)
    });
    // ... rest of app code
});

In this case, start creates a websocket url that is:

ws://127.0.0.1:8088/ari/events?app=some_app&api_key=special:s3cre+

The + seems to be interpreted as a space. If one calls: ari.connect('http://127.0.0.1:8088', 'special', 'secre%2B') (where %2B is url-encoded +), it goes through as before. I tried wrapping the username and password in encodeURIComponent in the start function (while using secre+ again), and it went without a hitch.

I don't think the Asterisk documentation prevents one from using special characters; either: the library should add URL-encoding as a safeguard against +, %, etc... or, issue a warning against using special characters.


Perhaps the strangest thing for me here is the Error: undefined part. I had to console.log(err) from the processError in node_modules/ari-client/lib/client.js function to reveal the 401. I noticed that resolve and reject is overwritten to be called only once; I think that muddled up the error message somehow?

chadxz commented 7 years ago

Thank you for taking the time to verify the issue. Since you have a narrow reproduction case and the fix in hand, would you be up for submitting a pull request with the fix?

danjenkins commented 7 years ago

I'd recommend fixing this as two separate PRs @glyphCezilleSantillan - one to fix the main issue and another to fix whatever issue you're facing with promises?

samuelg commented 7 years ago

Closing since the 2 PRs above should resolve the issues listed here.