Gtalk XMPP SASL authentication failed using mechanism X-OAUTH2?
android, google-oauth, xmpp
Solution
Here's a version working for me, using OAUTH2 tokens. The OAUTH2 scope is `https://www.googleapis.com/auth/googletalk` .
This code uses the Smack XMPP library.
The OAuth2 authentication mechanism :
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import javax.security.sasl.Sasl;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.util.Base64;
public class SALSGTalkOauthMechanism extends SASLMechanism {
private static final Logger log = Logger.getLogger(SALSGTalkOauthMechanism.class.getName());
public static final String NAME = "X-OAUTH2";
/**
* Constructor.
*/
public SALSGTalkOauthMechanism(SASLAuthentication saslAuthentication) {
super(saslAuthentication);
log.info("Creating SASL mechanism for GTalk (X-OAUTH2)");
}
@Override
public void authenticate(String username, String host, String accessToken) throws IOException, XMPPException {
this.hostname = host;
log.info("Authenticating to host "+host+" with key "+username);
String[] mechanisms = { "X-OAUTH2" };
Map<String, String> props = new HashMap<String, String>();
this.sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, this);
getSASLAuthentication().send(new AuthMechanism(getName(), Base64.encodeBytes(('\0'+username+'\0'+accessToken).getBytes())));
}
@Override
protected String getName() {
return NAME;
}
}
And the code to make it work together :
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import revevol.applications.cloudpulse.client.Probe;
import revevol.applications.cloudpulse.client.ProbeClient;
import revevol.applications.cloudpulse.client.ProbeClientUtils;
import com.google.api.client.auth.oauth2.Credential;
public class GTalkProbe implements Probe {
private static final Logger log = Logger.getLogger(GTalkProbe.class.getName());
public static final String PROBE_GTALK_IDENTIFIER = "gtalkprobe";
@Override
public void run(ProbeClient client, Properties properties) throws Exception {
log.info("Start running GTalkProbe.");
long startTimestamp = new Date().getTime();
Exception exception = null;
MessageReboundResult result = new MessageReboundResult();
Connection conn1 = null;
try {
Credential credential = ProbeClientUtils.getOAuth2Credentials(properties);
ConnectionConfiguration config = new ConnectionConfiguration("talk.google.com", 5222, "gmail.com");
config.setCompressionEnabled(true);
config.setSASLAuthenticationEnabled(true);
conn1 = new XMPPConnection(config);
SASLAuthentication.registerSASLMechanism("X-OAUTH2", SALSGTalkOauthMechanism.class);
SASLAuthentication.supportSASLMechanism("X-OAUTH2", 0);
conn1.connect();
log.info("Logging in");
conn1.login(ProbeClientUtils.getOAuthConsumerId(properties), credential.getAccessToken());
Presence presence = new Presence(Presence.Type.available);
presence.setStatus("My status");
conn1.sendPacket(presence);
ChatManager chatmanager = conn1.getChatManager();
String destination = "destination@gmail.com";
log.info("Sending chat message to " + destination);
String message = "PING : " + UUID.randomUUID().toString();
Chat chat = chatmanager.createChat(destination, new MessageListener(//TODO : here put your stuff));
Message msg = new Message(destination, Message.Type.chat);
msg.setBody(message);
chat.sendMessage(msg);
//Here you are
}
}
Problem
I am using GoogleTalk XMPP in my application for chatting. unable to create XMPP connection by using username and AuthToken with `Google authentication`. Now i am using `GoogleAuth2` for `authentication`. i tried to authenticate like this using access_token and email. by using `SASLMechanism`. but i am not able to connect to xmpp serv er, it gives error like this `SASL authentication failed using mechanism X-OAUTH2` ``` ConnectionConfiguration config = new ConnectionConfiguration(server_host, SERVER_PORT, SERVICE_NAME); config.setSASLAuthenticationEnabled(true); m_connection = new XMPPConnection(config); SASLAuthentication.registerSASLMechanism("X-OAUTH2", GoogleConnectSASLMechanism.class); SASLAuthentication.supportSASLMechanism("X-OAUTH2", 0); config.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled); try { m_connection.connect(); } catch (XMPPException e) { e.printStackTrace(); } ``` this is the class i am using for `SASLMechanism.` ``` public class GoogleConnectSASLMechanism extends SASLMechanism { public static final String NAME = "X-OAUTH2"; private String username = ""; private String sessionKey = ""; public GoogleConnectSASLMechanism(SASLAuthentication saslAuthentication) { super(saslAuthentication); } @Override protected String getName() { return NAME; } static void enable() { } @Override protected void authenticate() throws IOException, XMPPException { final StringBuilder stanza = new StringBuilder(); byte response[] = null; stanza.append("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"" + "mechanism=\"X-OAUTH2\"" + "auth:service=\"oauth2\"" + "xmlns:auth= \"http://www.google.com/talk/protocol/auth\">"); String composedResponse = "\0" + username + "\0" + sessionKey; response = composedResponse.getBytes("UTF-8"); String authenticationText = ""; if (response != null) { authenticationText = Base64.encodeBytes(response, Base64.DONT_BREAK_LINES); } stanza.append(authenticationText); stanza.append("</auth>"); // Send the authentication to the server Packet p=new Packet() { @Override public String toXML() { return stanza.toString(); } }; getSASLAuthentication().send(p); } public class Auth2Mechanism extends Packet { String stanza; public Auth2Mechanism(String txt) { stanza = txt; } public String toXML() { return stanza; } } /** * Initiating SASL authentication by select a mechanism. */ public class AuthMechanism extends Packet { final private String name; final private String authenticationText; public AuthMechanism(String name, String authenticationText) { if (name == null) { throw new NullPointerException( "SASL mechanism name shouldn't be null."); } this.name = name; this.authenticationText = authenticationText; } public String toXML() { StringBuilder stanza = new StringBuilder(); stanza.append("<auth mechanism=\"").append(name); stanza.append("\" xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"); if (authenticationText != null && authenticationText.trim().length() > 0) { stanza.append(authenticationText); } stanza.append("</auth>"); return stanza.toString(); } } } ``` How to authenticate the `Google Auth` by using SASL Mechanism ?