c# facebook xmpp x-facebook-platform

c# - Integrando el chat de Facebook



xmpp x-facebook-platform (5)

Hay un ejemplo en Python en el sitio de Facebook Developer que puede ser de uso: https://developers.facebook.com/docs/chat/

He escrito un programa para integrar el chat de usuario de Facebook en C #, sin embargo siempre obtengo <failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure> después de enviar el Respuesta al servidor.

He comprobado la clave API y el secreto de la aplicación, ambos son correctos. Parece que estoy pasando algunos parámetros erróneos al servidor.

Aquí está mi código.

private void GetDetailsButton_Click(object sender, EventArgs e) { TcpClient FacebookClient = new TcpClient(); FacebookClient.Connect("chat.facebook.com", 5222); NetworkStream myns = FacebookClient.GetStream(); string xml = "<?xml version=''1.0''?>" + "<stream:stream " + "id=''1'' " + "to=''chat.facebook.com'' " + "xmlns=''jabber:client'' " + "xmlns:stream=''http://etherx.jabber.org/streams'' " + "version=''1.0'' >"; StreamWriter mySw = new StreamWriter(myns); mySw.WriteLine(xml); //sending initial request mySw.Flush(); byte[] serverResponseByte = new byte[1024]; int myBytesRead = 0; StringBuilder myResponseAsSB = new StringBuilder(); //reading response from the server to see the supported authentication methods do { myBytesRead = myns.Read(serverResponseByte, 0, serverResponseByte.Length); myResponseAsSB.Append(System.Text.Encoding.UTF8.GetString(serverResponseByte, 0, myBytesRead)); } while (myns.DataAvailable); myResponseAsSB.Clear(); xml = "<auth " + "xmlns=''urn:ietf:params:xml:ns:xmpp-sasl'' " + "mechanism=''X-FACEBOOK-PLATFORM'' />"; mySw.WriteLine(xml); mySw.Flush(); //sending response to server to use X-FACEBOOK-PLATFORM //reading challenge send by the server do { myBytesRead = myns.Read(serverResponseByte, 0, serverResponseByte.Length); myResponseAsSB.Append(System.Text.Encoding.UTF8.GetString(serverResponseByte, 0, myBytesRead)); } while (myns.DataAvailable); myResponseAsSB.Replace("<challenge xmlns=/"urn:ietf:params:xml:ns:xmpp-sasl/">", ""); myResponseAsSB.Replace("</challenge>", ""); //converting challenge string to normal string byte[] myregularstrigbytes = Convert.FromBase64String(myResponseAsSB.ToString()); string myregularstring = System.Text.Encoding.UTF8.GetString(myregularstrigbytes); //I''ve hardcoded the accesstoken here for testing purpose. string SessionKey = AccessToken.Split(''|'')[1]; string response = ComposeResponse(myregularstring); byte[] myResponseByte = Encoding.UTF8.GetBytes(response.ToString()); string myEncodedResponseToSend = Convert.ToBase64String(myResponseByte); xml = String.Format("<response xmlns=/"urn:ietf:params:xml:ns:xmpp-sasl/">{0}</response>", myEncodedResponseToSend); mySw.WriteLine(xml); mySw.Flush(); //sending the response to the server with my parameters myResponseAsSB.Clear(); //checking if authentication succeed do { myBytesRead = myns.Read(serverResponseByte, 0, serverResponseByte.Length); myResponseAsSB.Append(System.Text.Encoding.UTF8.GetString(serverResponseByte, 0, myBytesRead)); } while (myns.DataAvailable); MessageBox.Show(myResponseAsSB.ToString()); } private string ComposeResponse(string serverresponse) { string version = serverresponse.Split(''&'')[0].Split(''='')[1]; string method = serverresponse.Split(''&'')[1].Split(''='')[1]; string nonce = serverresponse.Split(''&'')[2].Split(''='')[1]; string SessionKey = AccessToken.Split(''|'')[1]; long callId = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; string sig = "api_key=" + appId + "call_id=" + callId + "method=" + method + "nonce=" + nonce + "session_key=" + SessionKey + "v=" + "1.0" + AppSecret; MD5 md = MD5.Create(); var hash = md.ComputeHash(Encoding.UTF8.GetBytes(sig)); sig = hash.Aggregate("", (current, b) => current + b.ToString("x2")); return "api_key=" + HttpUtility.UrlEncode(appId) + "&call_id=" + HttpUtility.UrlEncode(callId) + "&method=" + HttpUtility.UrlEncode(method) + "&nonce=" + HttpUtility.UrlEncode(nonce) + "&session_key=" + HttpUtility.UrlEncode(SessionKey) + "&v=" + HttpUtility.UrlEncode("1.0") + "&sig=" + HttpUtility.UrlEncode(sig); }

He remitido a estos artículos la autenticación de chat de Facebook en C # y X-FACEBOOK-PLATFORM y mi tipo de aplicación es de Nativo / Escritorio.

¿Puede alguien apuntarme en la dirección correcta?

Edit: creo que el problema es al crear la firma, ¿hay alguna forma de verificar la firma creada?

Edición 1: de acuerdo con esta respuesta SO, el token de acceso contiene la clave de sesión después de la primera | personaje y pude encontrar el | personaje hasta hace 2 días, pero ahora no puedo encontrar el | el carácter en el token de acceso, es realmente extraño, entonces, ¿cómo puedo encontrar la clave de sesión ahora? (O tal vez debería irme a dormir ahora.)

Edición 2: es extraño que siempre haya obtenido el token de acceso en forma de <appId>|<sessionKey>|<digest> para la aplicación nativa / de escritorio. auth.promoteSession más búsquedas y descubrí que la clave de sesión debe extraerse de la api heredada auth.promoteSession y codificar los parámetros usando HttpUtility.UrlEncode lugar de HttpUtility.HtmlEncode .

Ahora he codificado el token de acceso (verificado en el depurador de token de acceso ), la clave de la sesión, la clave de la aplicación y el secreto de la aplicación aún me sale el mismo error <failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>

Edición 3: Me he estado golpeando la cabeza durante una semana y aún así esto no funciona, pero hoy encontré una actualización en la documentation que dice: Note that this needs to be over TLS (Transport Layer Security) or you''ll get an error. Supongo que necesito modificar mi código en consecuencia.

Edición 4: probé el código en la documentación y encontré que el valor de $SESSION_XML debería ser

$SESSION_XML = ''<iq type="set" id="4">''. ''<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>'';

Publicaré el código C # una vez que termine de convertirlo.


Llegará más rápido si comienza con una biblioteca XMPP existente. Aquí hay una lista: http://xmpp.org/xmpp-software/libraries/

Por ejemplo, deseará no haber codificado manualmente todo su XML en lugar de ejecutarlo a través del DOM muy pronto. Mientras tanto, pruebe todas sus entradas con estos caracteres: <>''"&


No tengo idea si este es el problema y no tengo tiempo para probar, pero su firma me parece mal. También recuerde que Facebook se trasladó a OAuth 2.0 a principios de septiembre , así que asegúrese de que su access_token sea correcto.

Prueba esto:

string sig = "api_key=" + appId + "call_id=" + callId + "method=" + method + "nonce=" + nonce + "session_key=" + SessionKey + "v=1.0" + APP_SECRET; MD5 md = MD5.Create(); var hash = md.ComputeHash(Encoding.UTF8.GetBytes(sig)); sig = hash.Aggregate("", (current, b) => current + b.ToString("x2")); var response = "api_key=" + appId + "&call_id=" + callId + "&method=" + method + "&nonce=" + nonce + "&session_key=" + SessionKey + "&v=1.0"; // response & signature response = string.Concat(Uri.EscapeDataString(response), "&", Uri.EscapeDataString(sig)) // base64 encode var myEncodedResponseToSend = Convert.ToBase64String( ASCIIEncoding.ASCII.GetBytes(response));


Para utilizar X-FACEBOOK-PLATFORM, necesitará la sesión de usuario que se proporciona con el flujo de autenticación heredado. Sin embargo, access_token contiene la sesión del usuario después de la | como has anotado en tu edit1.

Anunciamos en la última publicación del blog que access_token se cifrará y esto será obligatorio a partir del 1 de octubre. Hasta entonces, la opción se puede cambiar en la configuración de la aplicación avanzada http://developers.facebook.com/blog/post/553/ .

En el futuro, access_token podrá usarse para X-FACEBOOK-PLATFORM.


Tuve el mismo problema antes de intentar autenticarme utilizando X-FACEBOOK-PLATFORM. Encontré una solución que creo que puede ayudarte.

Biblioteca XMPP con Java Asmack compatible con X-FACEBOOK-PLATFORM

Aunque el código es Java, es fácil de entender cómo funciona. El truco consiste en obtener la clave secreta de la sesión de Facebook con su token OAuth 2.0. Tienes que usar un método en desuso llamado auth.promoteSession de esta manera:

https://api.facebook.com/method/auth.promoteSession?access_token=yourAccessToken

Luego, Facebook le proporciona la clave secreta de la sesión que debe usar como parámetro de la clave secreta de la aplicación. Para poder utilizar este método, debe deshabilitar el parámetro Eliminar las API obsoletas en esta page en la sección de configuración de edición y la pestaña de avance.

Espero que esto te ayude.