strophe / strophejs

Strophe.js is an XMPP library for JavaScript

Home Page:http://strophe.im/strophejs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Reconnection on the same Strophe instance causes a null reference exception

DmytroLapshyn opened this issue · comments

Given an XMPP server uses SCRAM-SHA1 authentication scheme, a subsequent reconnection performed on the same Strophe.Connection instance causes an 'cannot call match method of null' exception at the following line:

https://github.com/strophe/strophejs/blob/master/src/core.js#L3380

As far as I can understand the root cause of the issue, the SASLSHA1 authentication mechanism is self-modifying in terms of overwriting its onChallenge method implementation upon the first call to the method's onChallenge.

As long as this overwrite is not rolled back on invoking connection.reset(), any subsequent authentication attempts that assume a client-first challenge would result in the aforementioned error.

Would you please clarify if this is intentional, and one is not supposed to reuse a Strophe.Connection instance for re-connecting to the server? And, if this is a breaking change introduced in recent versions of Strophe, because I believe this issue did not exist in Strophe v1.2.x ?

Would you please clarify if this is intentional, and one is not supposed to reuse a Strophe.Connection instance for re-connecting to the server?

AFAIK it should be possible to call reset on a connection instance and then reuse it again and I'm not aware of anyone intentionally changing the mechanics of the SCRAM-SHA1 auth implementation.

So this appears to be a bug,.

And, if this is a breaking change introduced in recent versions of Strophe, because I believe this issue did not exist in Strophe v1.2.x ?

The same onChallenge overwriting is already there in version 1.2.0.

See here:

this.onChallenge = function (connection, challenge)

I guess now I understand why I haven't seen this behavior in 1.2.x

The thing is, I was using a fork called npm-strophe, where the SASL mechanism implementation in question looks quite different and does not use any overwriting:

https://github.com/cj0x39e/npm-strophe/blob/master/core.js#L3237

AFAIK it should be possible to call reset on a connection instance and then reuse it again

Indeed this is possible (and we do use it), however a call to reset does not seem to undo the overwriting, as it acts on a Strophe.Connection instance, while SASL mechanisms appear to exist at a more global level.

As one could see here: https://github.com/strophe/strophejs/blob/master/src/core.js#L1599

the reset implementation does not even seem to touch SASL mechanisms in any way.

The line you linked to does overwrite onChallenge. What do you mean it "does not use any overwriting"?

Apologies, my bad 😞
Could it be, then, that the new constructor semantics for SCRAMSHA1 is what leads to the unwanted effect?

As I am pretty sure that the version of StropheJS from the "npm-strophe" fork did not have problems with reusing a Connection instance provided one did call reset() properly.

Could it be, then, that the new constructor semantics for SCRAMSHA1 is what leads to the unwanted effect?

I think what might be happening is that SASL mechanisms are now instantiated earlier and then kept around (i.e. reused) while previously they were instantiated later (and replaced previous instances, thereby avoiding the problem you have).

Instead of overwriting onChallenge like that, a flag can be set and then checked in an if statement which splits into the two possible code paths.

Then the SASL mechanisms can have an optional reset method which must get called from Strophe.Connection.prototype.reset and which is responsible for resetting the mechanism's internal state (in this case clearing that flag).

Can confirm that bug...
btw. would be nice to have a auto reconnect feature on network failures for websocket connections...

This should now be fixed due to this commit: ae0131a