Smack 4.1.1 - EXTERNAL SASL authentication via smack-sasl-javax throws IllegalArgumentException

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.

Thanks for the very detailed and complete bug report. Logged as SMACK-670.

Created Handle empty array in SASLMechanism.authenticate() · Flowdalic/Smack@dedef30 · GitHub

I’m currently uploading Smack 4.1.2-SNAPSHOT, could you test (in a few minutes) and report back if it fixes the issue? Thanks.

Yes, this fixes the issue. I can log in successfully using smack-sasl-javax. Thanks!

Can you provide a fixed version of 4.1.1 for this? I can’t use any 4.1.x since 4.1.0-alpha6 because of this.

Thanks!

Use 4.1.2-SNAPSHOT until 4.1.2 is released, and pin that snapshot version if you needed a non-changing dependency.