I upgraded from Smack 4.0.7 to 4.1.1, and I found that EXTERNAL SASL authentication started failing due to an exception. This was with the smack-sasl-javax component, which should be equivalent to 4.0.7’s SASL implementation in its core library. smack-sasl-provided works fine, so at least there is a workaround.
In Smack 4.0.7, the following stanza is sent by the client to select EXTERNAL authentication:
In Smack 4.1.1, I see that changes have been added to comply with RFC6120 6.4.2. So with smack-sasl-provided, this stanza is sent:
=
In both cases, the client is able to log in successfully. I assume the server is being lenient in accepting “” as well as “=”. With smack-sasl-javax, however, an IllegalArgumentException is thrown:
java.lang.IllegalArgumentException: SASL authenticationText must not be null or empty (RFC6120 6.4.2)
at org.jivesoftware.smack.util.StringUtils.requireNotNullOrEmpty(StringUtils.java: 263)
at org.jivesoftware.smack.sasl.packet.SaslStreamElements$AuthMechanism.(Sasl StreamElements.java:42)
at org.jivesoftware.smack.sasl.SASLMechanism.authenticate(SASLMechanism.java:207)
at org.jivesoftware.smack.sasl.SASLMechanism.authenticate(SASLMechanism.java:190)
at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java: 190)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.loginNonAnonymously(XMPPTCPConnect ion.java:368)
at org.jivesoftware.smack.AbstractXMPPConnection.login(AbstractXMPPConnection.java :452)
at org.jivesoftware.smack.AbstractXMPPConnection.login(AbstractXMPPConnection.java :410)
(…)
The SASLMechanism.authenticate() method appears to be responsible for this:
private final void authenticate() throws SmackException, NotConnectedException {
byte[] authenticationBytes = getAuthenticationText();
String authenticationText;
if (authenticationBytes != null) {
authenticationText = Base64.encodeToString(authenticationBytes);
} else {
// RFC6120 6.4.2 "If the initiating entity needs to send a zero-length initial response,
// it MUST transmit the response as a single equals sign character ("="), which
// indicates that the response is present but contains no data."
authenticationText = “=”;
}
// Send the authentication to the server
connection.send(new AuthMechanism(getName(), authenticationText));
}
While debugging, I see that getAuthenticationText() returns an empty byte array, not a null reference, and Base64.encodeToString converts it to an empty string. This fails AuthMechanism’s input validation. I assume the “empty” authenticationText is correct, since both Smack 4.0.7 and Smack 4.1.1 with smack-sasl-provided give “empty” values and ultimately succeed in logging in. Therefore, SASLMechanism.authenticate should convert an empty byte array into “=”, like it does with null byte arrays.
This is with Java 7, using the smack-java7 component, which initializes the Base64 encoder as Java7Base64Encoder.