title: XMPP with Java Asmack library supporting X-FACEBOOK-PLATFORM
body: <p>I'm trying to make a Facebook Chat on Android with the Smack library. I've read the <a href="http://developers.facebook.com/docs/chat/">Chat API</a> from Facebook, but I cannot understand how I have to authenticate with Facebook using this library.</p>
  
  <p>Can anyone point me how to accomplish this?</p>
  
  <p><strong>Update</strong>: According to the no.good.at.coding answer, I have this code adapted to the Asmack library. All works fine except I receive as response to the login: not-authorized. Here is the code I use:</p>
  
  <pre><code>public class SASLXFacebookPlatformMechanism extends SASLMechanism
  {
  
      private static final String NAME              = "X-FACEBOOK-PLATFORM";
  
      private String              apiKey            = "";
      private String              applicationSecret = "";
      private String              sessionKey        = "";
  
      /**
       * Constructor.
       */
      public SASLXFacebookPlatformMechanism(SASLAuthentication saslAuthentication)
      {
          super(saslAuthentication);
      }
  
      @Override
      protected void authenticate() throws IOException, XMPPException
      {
  
          getSASLAuthentication().send(new AuthMechanism(NAME, ""));
      }
  
      @Override
      public void authenticate(String apiKeyAndSessionKey, String host,
              String applicationSecret) throws IOException, XMPPException
      {
          if (apiKeyAndSessionKey == null || applicationSecret == null)
          {
              throw new IllegalArgumentException("Invalid parameters");
          }
  
          String[] keyArray = apiKeyAndSessionKey.split("\\|", 2);
          if (keyArray.length &lt; 2)
          {
              throw new IllegalArgumentException(
                      "API key or session key is not present");
          }
  
          this.apiKey = keyArray[0];
          Log.d("API_KEY", apiKey);
          this.applicationSecret = applicationSecret;
          Log.d("SECRET_KEY", applicationSecret);
          this.sessionKey = keyArray[1];
          Log.d("SESSION_KEY", sessionKey);
  
          this.authenticationId = sessionKey;
          this.password = applicationSecret;
          this.hostname = host;
  
          String[] mechanisms = { "DIGEST-MD5" };
          Map&lt;String, String&gt; props = new HashMap&lt;String, String&gt;();
          this.sc =
                  Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,
                          this);
          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));
              Log.d("DECODED", decodedChallenge);
              Map&lt;String, String&gt; parameters = getQueryMap(decodedChallenge);
  
              String version = "1.0";
              String nonce = parameters.get("nonce");
              String method = parameters.get("method");
  
              long callId = new GregorianCalendar().getTimeInMillis() / 1000L;
  
              String sig =
                      "api_key=" + apiKey + "call_id=" + callId + "method="
                              + method + "nonce=" + nonce + "session_key="
                              + sessionKey + "v=" + version + applicationSecret;
  
              try
              {
                  sig = md5(sig);
                  sig = sig.toUpperCase();
              } catch (NoSuchAlgorithmException e)
              {
                  throw new IllegalStateException(e);
              }
  
              String composedResponse =
                      "api_key=" + URLEncoder.encode(apiKey, "utf-8")
                              + "&amp;call_id=" + callId + "&amp;method="
                              + URLEncoder.encode(method, "utf-8") + "&amp;nonce="
                              + URLEncoder.encode(nonce, "utf-8")
                              + "&amp;session_key="
                              + URLEncoder.encode(sessionKey, "utf-8") + "&amp;v="
                              + URLEncoder.encode(version, "utf-8") + "&amp;sig="
                              + URLEncoder.encode(sig, "utf-8");
  
              Log.d("COMPOSED", composedResponse);
  
              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&lt;String, String&gt; getQueryMap(String query)
      {
          Map&lt;String, String&gt; map = new HashMap&lt;String, String&gt;();
          String[] params = query.split("\\&amp;");
  
          for (String param : params)
          {
              String[] fields = param.split("=", 2);
              map.put(fields[0], (fields.length &gt; 1 ? fields[1] : null));
          }
  
          return map;
      }
  
      private String md5(String text) throws NoSuchAlgorithmException,
              UnsupportedEncodingException
      {
          MessageDigest md = MessageDigest.getInstance("MD5");
          md.update(text.getBytes("utf-8"), 0, text.length());
          return convertToHex(md.digest());
      }
  
      private String convertToHex(byte[] data)
      {
          StringBuilder buf = new StringBuilder();
          int len = data.length;
  
          for (int i = 0; i &lt; len; i++)
          {
              int halfByte = (data[i] &gt;&gt;&gt; 4) &amp; 0xF;
              int twoHalfs = 0;
  
              do
              {
                  if (0 &lt;= halfByte &amp;&amp; halfByte &lt;= 9)
                  {
                      buf.append((char) ('0' + halfByte));
                  }
                  else
                  {
                      buf.append((char) ('a' + halfByte - 10));
                  }
                  halfByte = data[i] &amp; 0xF;
              } while (twoHalfs++ &lt; 1);
          }
  
          return buf.toString();
      }
  }
  </code></pre>
  
  <p>And this, is the communication with the server with the sent and received messages:</p>
  
  <pre><code>PM SENT (1132418216): &lt;stream:stream to="chat.facebook.com" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0"&gt;
  
  
  PM RCV  (1132418216): &lt;?xml version="1.0"?&gt;&lt;stream:stream id="C62D0F43" from="chat.facebook.com" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0" xml:lang="en"&gt;&lt;stream:features&gt;&lt;mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"&gt;&lt;mechanism&gt;X-FACEBOOK-PLATFORM&lt;/mechanism&gt;&lt;mechanism&gt;DIGEST-MD5&lt;/mechanism&gt;&lt;/mechanisms&gt;&lt;/stream:features&gt;
  
  
  PM SENT (1132418216): &lt;auth mechanism="X-FACEBOOK-PLATFORM" xmlns="urn:ietf:params:xml:ns:xmpp-sasl"&gt;&lt;/auth&gt;
  
  
  PM RCV  (1132418216): &lt;challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl"&gt;dmVyc2lvbj0xJm1ldGhvZD1hdXRoLnhtcHBfbG9naW4mbm9uY2U9NzFGNkQ3Rjc5QkIyREJCQ0YxQTkwMzA0QTg3OTlBMzM=&lt;/challenge&gt;
  
  
  PM SENT (1132418216): &lt;response xmlns="urn:ietf:params:xml:ns:xmpp-sasl"&gt;YXBpX2tleT0zMWYzYjg1ZjBjODYwNjQ3NThiZTZhOTQyNjVjZmNjMCZjYWxsX2lkPTEzMDA0NTYxMzUmbWV0aG9kPWF1dGgueG1wcF9sb2dpbiZub25jZT03MUY2RDdGNzlCQjJEQkJDRjFBOTAzMDRBODc5OUEzMyZzZXNzaW9uX2tleT0yNjUzMTg4ODNkYWJhOGRlOTRiYTk4ZDYtMTAwMDAwNTAyNjc2Nzc4JnY9MS4wJnNpZz04RkRDRjRGRTgzMENGOEQ3QjgwNjdERUQyOEE2RERFQw==&lt;/response&gt;
  
  
  PM RCV  (1132418216): &lt;failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"&gt;&lt;not-authorized/&gt;&lt;/failure&gt;
  </code></pre>
  
  <p>As read in the <a href="http://forum.developers.facebook.net/viewtopic.php?id=93219">developers Facebook forum</a>, it is needed to disable the "Disable Deprecated Auth Methods" setting from the Facebook settings page of your app. But, even doing that, I can't login. And the session key is the second part of the OAuth token in the form AAA|BBB|CCC, I mean, BBB.</p>