2

I'm dealing with the facebook chat authentication using the X-FACEBOOK-PLATFORM SASL authentication mechanism.

I'm forming the user and password as explained in the facebook developer forum and the stackoverflow question.

The point is if I use the application_secret as password I can login, but according to the stackoverflow question (link below) it should be a session generated from the old rest api method auth.promoteSession

I want to use the old rest api method, in order to avoid distributing the application_secret in our desktop application jars.

So the question is, how have you managed to login with the auth.promoteSession????

I have read the following posts which have been of great help:

http://community.igniterealtime.org/message/205739#205739
XMPP with Java Asmack library supporting X-FACEBOOK-PLATFORM

And I'm using the class SASLXFacebookPlatformMechanism.java which comes fromt the igniterealtime post and it is registered correclty.

I have the xmpp_login and offline_access permisions. And I have disabled the Remove Deprecated Auth Methods, so I can called the old rest api methods, in this case: auth.promoteSession I'm using the client-side flow authentication into facebook as well.

So, using the application_secret as password I get:

<stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>X-FACEBOOK-PLATFORM</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features>
<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dmVyc2lvbj0xJm1ldGhvZD1hdXRoLnhtcHBfbG9naW4mbm9uY2U9NEIxRUQzNTA5MTQ5MDQxRTE4N0QyNTA0NTUzNjBDQjc=</challenge>
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>

But if I use the value returned by the auth.promoteSession I get:

<stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>X-FACEBOOK-PLATFORM</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features>
<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dmVyc2lvbj0xJm1ldGhvZD1hdXRoLnhtcHBfbG9naW4mbm9uY2U9MzhFQkUxOTUxNENGRUU4ODc2NzRDREQ0RjhBMUQ0QjI=</challenge>
<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>
Community
  • 1
  • 1
zageyiff
  • 465
  • 5
  • 10

2 Answers2

6

I have changed the version for Android and it works for me now

public class SASLXFacebookPlatformMechanism extends SASLMechanism {

    private static final String NAME              = "X-FACEBOOK-PLATFORM";

    private String              apiKey            = "";
    private String              accessToken        = "";

    /**
     * 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 accessToken) throws IOException, XMPPException {
        if (apiKey == null || accessToken == null) {
            throw new IllegalArgumentException("Invalid parameters");
        }

        this.apiKey = apiKey;
        this.accessToken = accessToken;
        this.hostname = host;

        String[] mechanisms = { "DIGEST-MD5" };
        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 = { "DIGEST-MD5" };
        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");

            String composedResponse =
                "method=" + URLEncoder.encode(method, "utf-8") +
                        "&nonce=" + URLEncoder.encode(nonce, "utf-8") +
                        "&access_token=" + URLEncoder.encode(accessToken, "utf-8") +
                        "&api_key=" + URLEncoder.encode(apiKey, "utf-8") +
                        "&call_id=0" +
                        "&v=" + URLEncoder.encode(version, "utf-8");
            response = composedResponse.getBytes();
        }

        String authenticationText = "";

        if (response != null) {
            authenticationText = Base64.encodeBytes(response);
        }

        // 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;
    }
}

This version requires only application id and access token

ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com", 5222);
config.setSASLAuthenticationEnabled(true);
mFbConnection = new XMPPConnection(config);

try {
    SASLAuthentication.registerSASLMechanism("X-FACEBOOK-PLATFORM", SASLXFacebookPlatformMechanism.class);
    SASLAuthentication.supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);
    mFbConnection.connect();
    mFbConnection.login(apiKey, accessToken, "Application");
} catch (XMPPException e) {
    mFbConnection.disconnect();
    e.printStackTrace();
}

I hope this will help.

bazukas
  • 89
  • 2
  • 5
  • @hleinone I too am trying to implement a facebook chat in ma android app, but I am not getting the SASLMechanism class to be imported. To we have to download any library or jar file to import this. If please provide a valid link to download.. – Arun PS Jan 29 '13 at 07:06
  • You'll need to use the [Smack](http://www.igniterealtime.org/projects/smack/index.jsp) library. – hleinone Jan 29 '13 at 08:42
0

Yes it apears to me, you need both. The code from XMPP with Java Asmack library supporting X-FACEBOOK-PLATFORM needed adjusting to include the application secret, as well as the session secret (as the password).

this.apiKey = keyArray[0];
    Log.d("API_KEY", apiKey);
    this.applicationSecret = "################################";
    Log.d("SECRET_KEY", applicationSecret);
    this.sessionKey = keyArray[1];
    Log.d("SESSION_KEY", sessionKey);

    this.authenticationId = sessionKey;
    this.password = applicationSecret;
    this.hostname = host;

swaping out the ######################## for your appSecret (found in your dev area)

This is not clear from the docs or the post IMO. Session secret was aquired through FB.getSession() but other options work too.

Community
  • 1
  • 1
Instine
  • 2,342
  • 1
  • 14
  • 7