I am quite stuck on implementing facebook chat in my android application. I am using XMPP connection offered by aSmack library. Everything works fine, if i'm using PLAIN mechanism and my regular facebook username and password, like so
SASLAuthentication.supportSASLMechanism("PLAIN"); xmpp.login("my_username@mail.com", "my_password");
But if i'm using X-FACEBOOK-PLATFORM mechanism to login with my app id and access token, then i am getting always not authrized error.
This is my main login method:
public void testLogin(){
SASLAuthentication.registerSASLMechanism("X-FACEBOOK-PLATFORM", SASLXFacebookPlatformMechanism.class);
SASLAuthentication.supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);
ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com",5222);
config.setSASLAuthenticationEnabled(true);
config.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled);
XMPPConnection xmpp = new XMPPConnection(config);
try {
//Async connecting to XMPPConnection
new ConnectXMPP().execute(xmpp).get();
Log.i("XMPPClient",
"Connected to " + xmpp.getHost());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
try {
SmackConfiguration.setPacketReplyTimeout(1500);
xmpp.login("145537185371985731", "145537185371985731|W3-5DTut4qFoNuBapOI-f5Bo_eQ", "Application");
Log.i("10201970684380516", "Logged in to " + xmpp.getHost());
} catch (XMPPException e) {
e.printStackTrace();
}
}
And this is my SASLXFacebookPlatformMechanism class
public class SASLXFacebookPlatformMechanism extends SASLMechanism {
private static final String NAME = "X-FACEBOOK-PLATFORM";
private String apiKey = "";
private String access_token = "";
/**
* Constructor.
*/
public SASLXFacebookPlatformMechanism(SASLAuthentication saslAuthentication) {
super(saslAuthentication);
}
@Override
protected void authenticate() throws IOException, XMPPException {
getSASLAuthentication().send(new AuthMechanism(NAME, ""));
}
@Override
public void authenticate(String apiKey, String host, String acces_token)
throws IOException, XMPPException {
if (apiKey == null || acces_token == null) {
throw new IllegalArgumentException("Invalid parameters");
}
this.access_token = acces_token;
this.apiKey = apiKey;
this.hostname = host;
String[] mechanisms = { NAME };
Map<String, String> props = new HashMap<String, String>();
this.sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,
this);
authenticate();
}
@Override
public void authenticate(String username, String host, CallbackHandler cbh)
throws IOException, XMPPException {
String[] mechanisms = { NAME };
Map<String, String> props = new HashMap<String, String>();
this.sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,
cbh);
authenticate();
}
@Override
protected String getName() {
return NAME;
}
@Override
public void challengeReceived(String challenge) throws IOException {
byte[] response = null;
if (challenge != null) {
String decodedChallenge = new String(Base64.decode(challenge));
Map<String, String> parameters = getQueryMap(decodedChallenge);
String version = "1.0";
String nonce = parameters.get("nonce");
String method = parameters.get("method");
long callId = new GregorianCalendar().getTimeInMillis();
String composedResponse = "api_key="
+ URLEncoder.encode(apiKey, "utf-8") + "&call_id=" + callId
+ "&method=" + URLEncoder.encode(method, "utf-8")
+ "&nonce=" + URLEncoder.encode(nonce, "utf-8")
+ "&access_token="
+ URLEncoder.encode(access_token, "utf-8") + "&v="
+ URLEncoder.encode(version, "utf-8");
response = composedResponse.getBytes("utf-8");
}
String authenticationText = "";
if (response != null) {
authenticationText = Base64.encodeBytes(response,
Base64.DONT_BREAK_LINES);
}
// Send the authentication to the server
getSASLAuthentication().send(new Response(authenticationText));
}
private Map<String, String> getQueryMap(String query) {
Map<String, String> map = new HashMap<String, String>();
String[] params = query.split("\\&");
for (String param : params) {
String[] fields = param.split("=", 2);
map.put(fields[0], (fields.length > 1 ? fields[1] : null));
}
return map;
}
}
And there's the exception i am getting always.
D/SMACK﹕ 09:26:38 ɣetrɔ SENT (308528663): <auth mechanism="X-FACEBOOK-PLATFORM" xmlns="urn:ietf:params:xml:ns:xmpp-sasl"></auth>
02-26 21:26:38.871 3810-3837/com.example.transporter D/SMACK﹕ 09:26:38 ɣetrɔ RCV (308528663): <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>dmVyc2lvbj0xJm1ldGhvZD1hdXRoLnhtcHBfbG9naW4mbm9uY2U9QzkyQjg1M0UwODFCQzNEQzI1NzRBQ0ZENUJDQUQyNTQ=</challenge>
02-26 21:26:38.872 3810-3836/com.example.transporter D/SMACK﹕ 09:26:38 ɣetrɔ SENT (308528663): <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">YXBpX2tleT0xMDIwMTk3MDY4NDM4MDUxNiZjYWxsX2lkPTE0MjQ5Nzg3OTg4NzEmbWV0aG9kPWF1dGgueG1wcF9sb2dpbiZub25jZT1DOTJCODUzRTA4MUJDM0RDMjU3NEFDRkQ1QkNBRDI1NCZhY2Nlc3NfdG9rZW49MTQ1MjYwMjYzODMwMTM1MCU3Q1czLTVEVHV0NHFGb051QmFwT0ktZjVCb19lUSZ2PTEuMA==</response>
02-26 21:26:39.178 3810-3837/com.example.transporter D/SMACK﹕ 09:26:39 ɣetrɔ RCV (308528663): <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized/></failure></stream:stream>
02-26 21:26:39.181 3810-3810/com.example.transporter W/System.err﹕ SASL authentication failed using mechanism X-FACEBOOK-PLATFORM:
3810-3810/com.example.transporter W/System.err﹕ at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:342)
02-26 21:26:39.184 3810-3810/com.example.transporter W/System.err﹕ at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:230)
02-26 21:26:39.184 3810-3810/com.example.transporter W/System.err﹕ at com.example.transporter.activity.MainActivity.testLogin(MainActivity.java:188)
02-26 21:26:39.184 3810-3810/com.example.transporter W/System.err﹕ at com.example.transporter.activity.MainActivity$1.onClick(MainActivity.java:135)