X-FACEBOOK-PLATFORM

This is an attempt to explain how to authenticate with facebook platform to access facebook chat in your ASP.NET applications. The documentation provided by facebook is very rudimentary to the say the least. They have not explained anything: for example, how to create signatures, how to create hashes. Creating a signature and hashes depends on what parameters are passed to the hashing function. Obviously, if the developer does not know what parameters or values to hash, they cannot create the correct hash required by the facebook server.

Keeping this in mind, here are some of the findings that I collected to make it easier for us to integrate with facebook chat - especially in .NET.

You would need understanding and grasp of XMPP (http://xmpp.org/rfcs/rfc3920.html). You may also encounter XMPP with its original name, Jabber.

XMPP understanding is required if you want to completely integrate chat (not only facebook but others like google talk). The goal of this documentation is to get you started with facebook authentication. Rest is very simple once you are authenticated and once you are upto the mark on XMPP, developing the chat app should be a breeze. Basically, whatever server-client interaction goes on using this protocol, is based on plain text XML messages that are sent BASE64 encoded to the server.

This document mostly talks about facebook chat because documentation on authentication with facebook chat is missing very badly from the Internet. Once you authenticate yourself with facebook, just follow XMPP guidelines and you are all set. The hardest of all is authentication and that is discussed here.

You would need FBConnect Class Class.

=
Basically to integrate facebook chat within your application, you can communicate using Jabber which is a name for XMPP protocol. XMPP works by sending XML messages back and forth between the client and server. Server: chat.facebook.com Port: 5222 There are 2 ways of authentication:====== >> >>
 * ======MD5 DIGEST authentication where username and password is sent via app to server======
 * Your username is your facebook username like this: facebookusername@chat.facebook.com
 * You have to first get your facebook username for this to work. You can get username from this link: @http://www.facebook.com/username/
 * Second authentication mechanism is X-FACEBOOK-PLATFORM and this is what we discuss here.

=GETTING STARTED=

The flow of app looks something like this. I am posting ASP.NET code (it is not complete but just to illustrate the flow and algorithm). Following is the code:
code format="vbnet" Dim mytcpclient As New TcpClient mytcpclient.Connect("chat.facebook.com", 5222) Dim myns As NetworkStream = mytcpclient.GetStream

Dim myMessage As String = ""

Dim mySW As New System.IO.StreamWriter(myns) mySW.WriteLine(myMessage) mySW.Flush Dim myMessage2 =  mySW.WriteLine(myMessage2) mySW.Flush

Dim serverResponseByte(1024) As Byte Dim myBytesRead As Integer = 0 Dim myResponseAsSB As New StringBuilder Do

myBytesRead = myns.Read(serverResponseByte, 0, serverResponseByte.Length) myResponseAsSB.Append(System.Text.Encoding.UTF8.GetString(serverResponseByte, 0, myBytesRead))

Loop While (myns.DataAvailable) code

After above code is executed, you get back a XML string like the following:
code format="xml"  X-FACEBOOK-PLATFORM DIGEST-MD5  dmVyc2lvbj0xJm1ldGhvZD1hdXRoLnhtcHBfbG9naW4mbm9uY2U9QjNBOUU4NzJFQUJGNkQ5RDM0RTZDNjgzMjkyMTBGOEQ=

code

=
Use LINQ or XMLDOCUMENT to parse this XML (stored in myResponseAsSb in code sample above) and retrieve the element's value. Use the following code to decode the BASE64 encoded. Again code is not with the flow of the app - it is shown as an illustration. you would want to create a separate method for this and pass the arguments. I have hardcoded the values for now to keep the sample going.======

code format="vbnet" Dim mybase64 As String = "dmVyc2lvbj0xJm1ldGhvZD1hdXRoLnhtcHBfbG9naW4mbm9uY2U9NTZDNERCMzE0RkUxMjYxM0U0OTYwQ0E3M0IyRUMyNzY=" Dim myregularstrigbytes As Byte = Convert.FromBase64String(mybase64) Dim myregularstring As String = System.Text.Encoding.UTF8.GetString(myregularstrigbytes) Response.Write(myregularstring) code

**Before I move on with code, following is an outline of steps to follow**

 * 1) Arrange API_KEY, CALL_ID, METHOD, NONCE, SESSION_KEY and V in an alphabetical order.
 * 2) V would always be v=1.0
 * 3) CALL_ID can be system.datetime.ticks
 * 4) METHOD received from challenge
 * 5) NONCE received from challenge
 * 6) Make a string like this api_key=valuecall_id=valuemethod=valuenonce=valuesession_key=valuev=1.0APP_SECRET
 * 7) <span style="background-color: #ffff00; font-family: 'Arial Black',Gadget,sans-serif;">Notice there is no & between the variables
 * 8) <span style="background-color: #ffff00; font-family: 'Arial Black',Gadget,sans-serif;">Hash the string using MD5 cryptography and convert to Hex (tostring("x2")). Make sure to user lowercase x2 (dont use X2) because there is a difference and server can get tripped.
 * 9) <span style="background-color: #ffff00; font-family: 'Arial Black',Gadget,sans-serif;">The MD5 hash is the signature you need to pass back as response to the challenge
 * 10) <span style="background-color: #ffff00; font-family: 'Arial Black',Gadget,sans-serif;">Now, make another string. same as in number vi but this time url encode it and with &. Append the SIGNATURE to this string by using &sig=value_of_signature
 * 11) <span style="background-color: #ffff00; font-family: 'Arial Black',Gadget,sans-serif;">Now encode the string in step 10 above to BASE64 and send it back to server

=ORGANIZING KEY VALUE PAIRS AND CREATING SIGNATURE=

=
Here is code to first create the string mentioned in step 6. Again code is not an integrated example but bits and pieces to show the logic, flow and algorithm. I keep on repeating this because someone might just comment that code does not work. So, you have to integrate it using the steps provided for it to work.====== code format="vbnet" Dim myparams As New SortedDictionary(Of String, String) myparams.Add("api_key", fbconnect.APIKEY) myparams.Add("call_id", System.DateTime.Now.Ticks.ToString) myparams.Add("method","RETRIEVE_METHOD_FROM STRING THAT YOU RECEIVED FROM CHALLENGE STRING") mparams.Add("nonce","RETRIEVE NONCE FROM STRING THAT YOU RECEIVE FROM CHALLENGE") myparams.add("session_key"),fbconnect.Session_Key) myparams.Add("v", "1.0")

code

** NOTE IAM NOT PASSING APPSECRET RIGHT NOW. IT WILL BE APPENDED IN THE NEXT STEP ON HASHING .** After you have created the sorted dictionary, it is time to Hash using the following function:
code format="vbnet" Private Function ComputeHash(ByVal myparams As SortedDictionary(Of String, String), ByVal AppSecretKey As String) As String Dim parametersForSig As New StringBuilder For Each myKey As String In myparams.Keys parametersForSig.Append(String.Format("{0}={1}", myKey, myparams(myKey))) Next parametersForSig.Append(AppSecretKey) Dim myMD5 As New System.Security.Cryptography.MD5CryptoServiceProvider Dim myData As Byte = myMD5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(parametersForSig.ToString))

Dim md5HashToReturn As New StringBuilder Dim i As Integer = 0 For i = 0 To myData.Length - 1 md5HashToReturn.Append(myData(i).ToString("x2"))

Next Return md5HashToReturn.ToString.ToLower

End Function code

=CREATING FINAL STRING FOR RESPONSE TO CHALLENGE FROM FACEBOOK=

Once you have the hash value that is the signature that you need. So now do STEP 10
code format="vbnet" Dim sb As New StringBuilder sb.Append(String.Format("{0}={1}&", myKey, myparams(myKey))) Next sb.Append("RETURN VALUE FROM MD5 HASHING FUNCTION")

code

BASE64 ENCODE THE SB (stringbuilder object instantiated above as sb) LIKE THIS
code format="vbnet" Dim myResponseByte as byte=system.text.encoding.utf8.getbytes(sb.tostring) Dim myEncodedResponseToSend as string=convert.toBase64String(myResponseByte)

code

Now it is time to send it back to server. This would be your RESPONSE TO THE CHALLENGE sent earlier. How you send the response. Well you just send another XML packet. Which goes like this:
code format="xml" <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">BASE64 ENCODED STRING FROM PAST STEP

code

Once authenticated, you get a message of AUTHENTICATED OR NOT AUTHORIZED in XML from server.
=WHAT NOW?= well all these messages are specified in the XMPP protocol specification @http://xmpp.org/rfcs/rfc3920.html You have to read the XMPP specification to find out how to send messages. It is really very simple after authentication. all chat messages and everything is done by sending XML back and forth. So just read up the RFC. I am also reading it to see WHAT MESSAGES TO USE TO RETRIEVE USERS AND SEND MESSAGES. As I said, it is just simple text XML so very easy to do ONCE AUTHENTiCATED. AUTHENTICATION is the challenging part here because there is really no documentation on facebook to show how to create signature, and what exactly to send back to the server and in what format. As you can see, it is pretty involved. Rest is easy. So if anybody has further knowledge of XMPP please share here. There is not much help on this topic on the web and let's try to help the community by contributing. Email me at **rafayali on gmail.com** if you want to contribute.

=NEXT STEPS=


 * Send response back to server using network stream
 * Read XMPP documentation on how to work next after authentication and what XML messages the server expects.
 * Read [] to get basic nutshell idea about XMPP messages (ALONGWITH THE RFC)
 * Implementing a complete protocol is an overwhelming task and you can use .NET XMPP implementations if you are not too keen on learning XMPP. Here are some .NET XMPP implementation:
 * Jabber.NET
 * agsXMPP
 * Matrix for Silverlight
 * Ubiety - this is a basic implementation and supports RFC-3920 and RFC-3921

<span style="background-color: #ffff00; font-family: Verdana,Geneva,sans-serif;">REMEMBER: Above libraries can be used AS IS only for facebook <span style="background-color: #ff0000; color: #ffffff; font-family: Verdana,Geneva,sans-serif;">DIGEST-MD5 <span style="background-color: #ffff00; font-family: Verdana,Geneva,sans-serif;"> mechanism. As stated above, in this mechanism the user would need to first make a username on facebook (link given above where this was discussed), and then use that username in the format <span style="background-color: #ff0000; color: #ffffff; font-family: Verdana,Geneva,sans-serif;">username@chat.facebook.com <span style="background-color: #ffff00; font-family: Verdana,Geneva,sans-serif;"> to login to facebook chat. This is very inconvenient for the users to remember that the domain must be chat.facebook.com. It is also not seamless.

<span style="background-color: #ffff00; font-family: Verdana,Geneva,sans-serif;">Therefore, <span style="background-color: #008000; color: #ffffff; font-family: Verdana,Geneva,sans-serif;">facebook recommends using X-FACEBOOK-PLATFORM authentication. <span style="background-color: #ffff00; font-family: Verdana,Geneva,sans-serif;"> As far as my knowledge goes, none of the above support this mechanism because it is facebook proprietary and not an XMPP standard. So, you would need the directions provided in this wiki page alongwith the XMPP libraries.