As I said initially, the version (or perhaps configuration) of jabberd on my server does not send any stream:features tag. I just tried using flash:stream and I get the same situation, I send flash:stream and get a flash:stream but never any features tag.
Looking through the XIFF code for XMPPSocketConnection, the incoming data is handled by bSocketReceivedData(…). Within that method, there is a switch statement on the nodeName. The two nodeNames I care about would be stream:stream or stream:features which call handleStream(…) and handleStreamFeatures(…) in XMPPConnection.
The handleStream(…) method will set the sessionID and domain then check for any children and if a stream:features is found it passes that to handleStreamFeatures(…).
The method handleStreamFeatures(…) will eventually call beginAuthentication() (after configureAuthMechanisms()) and this is the only location I’ve found where beginAuthentication() is called.
Given that a server could send the stream:features... tag as a separate message from the stream:stream... tag, I’m not sure what the best solution here is. You cannot simply assume that if you didn’t get the features tag with the initial stream that there isn’t going to be one. That’s why I used a 4 second timer that kicks off at onConnectSuccess and uses IQ with AuthExtension to complete the login cycle. In my case, to compute the digest I needed the sessionID and so added a public method getSessionID() to XMPPConnection. I suppose I could have subclassed XMPPSocketConnection and added the method and integrated my 4 second timer, etc, then that should protect me from future updates to the XMPPConnection.
One (unrelated) bug I may have found is that in the AuthExtension, if you attempt to set a digest without setting a password first, you get an error. This is due to the set function for digest which does not check myPasswordNode for null prior to calling removeNode on it. The set password method has a similar situation which it handles by first creating an empty node if the node is null, then calling removeNode() and setting the node to null (seems like you could just check for null and only call removeNode() if the node is not null).
I certainly understand your limited time constraints and in the grand scheme of things, integrating some of the newer features (like the TLS/crypto solution posted by Dustin which seems to be highly requested) should probably take precedence. I do have a work-around and so there’s nothing really stopping me. I was more interested if I had simply missed the correct approach to take in my situation.