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:
Line 3129 in 6fca47a
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...