Tercera parte de esta guía de introducción a la programación de aplicaciones en Facebook. Si seguiste la primera y la segunda parte, a estas alturas ya le habrás perdido el medio a muchos de los conceptos clave (tipos de aplicaciones, SDKs, Social Plugins, Open Graph, XFBML, Insights). Pero hay otros conceptos igualmente importantes que todavía no conocemos. Hoy vamos a tratar la autenticación OAuth, el SDK de JavaScript a fondo, y veremos cómo crear diálogos.

Paso 1 – Autenticación

Vamos a añadir un sistema de autenticación mediante el Social Plugin ‘Login Button’, el diálogo OAuth, y el protocolo de autenticación OAuth. No te asustes, pues tras tanta palabreja se esconde una única línea de código HTML :)

OAuth

OAuth es un protocolo estándar que permite realizar autenticación segura contra una determinada API. Facebook en concreto se ciñe al estándar OAuth 2.0. Gracias a las herramientas que nos ofrece Facebook, no será necesario que conozcamos los entresijos de este protocolo, pero como siempre, sí es muy recomendable conocerlo.

En primer lugar, vamos a crear el Login Button. Como ya sabemos, accedemos a la página del plugin, completamos el formulario, y obtenemos su código HTML, que será similar a éste:

<div class="fb-login-button" data-show-faces="false" data-width="200" data-max-rows="1"></div>

Con sólo poner eso, ya tendremos el Login Button . ¿Y qué ocurrirá cuando lo pulsemos? Se desplegará automáticamente un diálogo OAuth (¿recuerdas los diálogos? Hablamos sobre ellos en la primera parte) que nos solicitará permiso para que la aplicación pueda acceder a nuestra información básica:

Con esto quizás sea suficiente. Pero vamos a enriquecerlo un poco, y en lugar de solicitar sólo la información básica, vamos a pedir permisos también para poder publicar nuevas noticias en su muro. Si recuerdas, en el apartado “Autenticación y permisos” de la primera parte de esta guía, hablamos de los distintos tipos de permisos. Puedes volver a consultar la lista completa de todos los que hay disponibles. En concreto el permiso para publicar en el muro se llama ‘publish_stream’. Para solicitarlo, debemos actualizar el código que genera el Loggin Button añadiendo el atributo ‘scope’ (puedes ver más sobre los atributos de Login Button en su documentación). Nos quedaría así:

<div class="fb-login-button" data-show-faces="false" data-width="200" data-max-rows="1" scope="publish_stream" ></div>

Y el nuevo diálogo OAuth:

Como vemos, ha funcionado correctamente, y ahora también solicita permisos para publicar en el muro. Ver ejemplo.

Atributo ‘scope’

Al código HTML que de define el Login Button le hemos añadido un atributo llamado ‘scope’ en el que podemos añadir una lista de permisos, de entre todos los disponibles, separados por comas. Estos permisos serán los que se soliciten cuando se despliegue el diálogo OAuth.

Mientras se escribe esta guía, en la documentación oficial del Login Button no hay mención a un atributo llamado ‘scope’. Sin embargo, sí hablan del atributo ‘perms’. Realmente son el mismo, pero para guardar coherencia con el estándar OAuth 2, le han cambiado el nombre a ‘scope’.

Paso 2 – Conocer el SDK JavaScript

Hasta ahora no hemos usado directamente el SDK de JavaScript. Únicamente lo hemos cargado indicándole algunos valores, como por ejemplo que renderice automáticamente todos los objetos XFBML (gracias a eso hemos podido incluir los Social Plugins).

Vamos a revisar algunos métodos que nos van a ser especialmente útiles para nuestra demo (recuerda que puedes consultar la documentación completa del SDK de JavaScript en http://developers.facebook.com/docs/reference/javascript/):

FB.api

Este método es el que nos permitirá realizar consultas al Graph API, que como vimos en la primera parte, es la herramienta donde todos los objetos de Facebook (personas, páginas, imágenes, etc.) están interconectados, y a la que podemos invocar para realizar consultas o modificaciones. Este método acepta 4 parámetros:

  1. path - String con la ruta al API.
  2. method - Tipo de petición (GET, POST o DELETE).
  3. params - Objeto con los parámetros de la consulta (si los necesitara).
  4. cb - Función callback.

Usualmente sólo serán necesarios path y cb.

FB.getLoginStatus

Permite determinar si el usuario ha iniciado sesión y está conectado con nuestra aplicación. Acepta dos parámetros:

  1. cb - Función callback con el parámetro ‘response’.
  2. force - Booleano que obligar a recargar el estado de login.

Cuando se invoca a este método, se realiza una consulta HTTP que devuelve el objeto ‘response’ de la función callback. Este objeto tiene la siguiente estructura:

{
    status: 'connected',
    authResponse: {
        accessToken: '...',
        expiresIn:'...',
        signedRequest:'...',
        userID:'...'
    }
}

Si el objeto response contiene un objeto authResponse, sabremos con certeza que el usuario ha iniciado sesión y que está conectado a nuestra aplicación. Los campos accessToken y userID serán muy útiles para hacer llamadas a la API de Graph API. Pero no te preocupes por esto, ya que el SDK JavaScript se encarga de hacer todas las gestiones por nosotros como luego veremos sin necesidad de manejar nosotros esos parámetros ;)

FB.getAuthResponse

Su funcionamiento es equivalente al del método FB.getLoginStatus. La única diferencia es que, en lugar de devolver un objeto response, sólo devuelve su campo authResponse. Es decir, llamaremos a FP.getAuthResponse cuando tengamos la certeza de que el usuario ha iniciado sesión (y está conectado a nuestra aplicación) y queramos obtener información acerca de la sesión.

FB.init

Este es el único método que hemos invocado directamente hasta ahora. Se encarga de inicializar el SDK. Acepta un único parámetro, options, de tipo objeto, que incluye todas las propiedades que queramos establecer. En concreto, hemos usado estas propiedades (existen más):

  • appId – String con el ID público de nuestra aplicación.
  • status – Booleano que indica si se debe o no comprobar el estado.
  • cookie – Booleano que habilita o deshabilita el soporte para la cookie. Ésta podrá usarse posteriormente para que, desde el servidor, por ejemplo en PHP, se realicen peticiones al API.
  • xfbml – Booleano que indica si se deben o no renderizar los objetos de tipo XFBML disponibles en la página. Gracias a esto, se han generado automáticamente hasta ahora los social plugins que hemos definido.
  • channelURL – String con la URL del fichero channel.html. Usándolo se evitan algunos errores. Consulta la documentación de este método para saber más.
  • oauth – Booleano que habilita o deshabilita soporte para OAuth 2.0. Tenlo siempre a true, pues muy pronto sólo se permitirá autenticación OAuth 2.0.

FB.login

Este método se encarga de gestionar el login por nosotros. Es decir, renderiza el diálogo OAuth con los permisos necesarios, y gestiona la respuesta devuelta por éste. No lo vamos a invocar directamente, pero ten en cuenta que el Login Button por debajo utiliza este método.

Tan solo acepta dos parámetros:

  1. cb - Función callback para gestionar la respuesta del usuario.
  2. opts - Objeto para modificar el comportamiento del login. Tan solo tiene una propiedad, ‘scope’, que como vimos más arriba acepta un string de los permisos que solicitamos, separados por coma.

FB.logout

Cierra la sesión del usuario. Sólo acepta un parámetro:

  1. cb - Función callback para gestionar el cierre de sesión.

FB.ui

Es el responsable de renderizar por nosotros los diálogos. Ya lo hemos visto en funcionamiento cuando hemos pulsado el Login Button y se ha desplegado el diálogo OAuth. Pero, por supuesto, también podremos invocar a mano este método siempre que deseemos mostrar cualquier otro diálogo.

Acepta dos parámetros:

  1. params - Objeto con todas las propiedades de configuración. Cada diálogo tiene sus propias propiedades (en la documentación de cada uno podrás conocerlas). Además, hay dos propiedades globales a todos los diálogos:
    1. method - String con el nombre del diálogo que se desea mostrar. Obligatorio.
    2. display - String que indica la forma en que se mostrará el diálogo, por ejemplo ‘popup’ . Opcional.
  2. cb - Función callback para manejar la respuesta.

FB.Event.subscribe

JavaScript es un lenguaje dirigido por eventos. Siguiendo este paradigma, el SDK JavaScript genera una serie de eventos a los que podemos suscribirnos para ejecutar una función callback. Este método acepta dos parámetros:

  1. name – String con el nombre del evento al que nos queremos suscribir.
  2. fb – Función callback que se ejecutará cuando se dispare el evento.

Entre los posibles eventos están auth.loginauth.authResponseChangeauth.statusChangeauth.logout además de otros muchos. Algunos de estos eventos generan un objeto que se pasará como parámetro a su función callback. Revisa la documentación para conocer más detalles.

Del mismo modo que nos podemos suscribir a un evento, también nos podemos desuscribir de él, mediante el método FB.Event.unsubscribe.

FB.XFBML.parse

Si bien en la demo no vamos a invocar este método, convine conocerlo, pues se ejecuta igualmente. En las propiedades de inicialización del SDK establecimos el valor xfbml a true. Esto significa que será el método FB.init el que llame a FB.XFBML.parse automáticamente por nosotros. Si no fuera así, lo podríamos invocar a mano con los siguientes parámetros:

  1. dom – Elemento DOM raíz a partir del cual se parsearán todos sus hijos XFBML.
  2. cb – Función callback.

Resto de métodos

Todavía quedan algunos métodos del SDK JavaScript. Dos de ellos (FB.Data.query y FB.Data.waitOn) no los hemos visto, ya que quedarán obsoletos a partir del 1 de enero de 2012 (su comportamiento se puede llevar a cabo mediante FB.api). El resto de métodos tratan sobre canvas; es decir, para gestionar aspectos gráficos relacionados con el elemento iframe donde se ubican las aplicaciones que se empotran en la página de Facebook. Estos métodos sobre canvas los veremos en la siguiente parte.

Paso 3 – Juntándolo todo

Volviendo a nuestra demo, hemos visto que ésta ya nos permite autenticarnos. Pero esto por sí solo no es algo muy útil. Por eso ahora queremos que haga más cosas. En concreto:

  • Queremos que cuando el usuario haya iniciado sesión, ya no se muestre el Login Button.
  • Cuando haya iniciado sesión, se mostrará un botón para cerrar sesión.
  • Además, consultaremos al Graph API algunos datos del usuario para mostrar su nombre y su avatar.
  • Añadiremos un botón que publicará automáticamente una historia en su muro.
  • Mostraremos un diálogo para invitar a nuestros amigos a usar la aplicación.
  • De paso, y por simplificar, vamos a eliminar el plugin Live Stream y el plugin del botón “Me gusta”.

¿Parece mucho? Vas a ver qué sencillo es :) Añadimos este código HTML:

    <div id="user-box" style="text-align:center; display:none;">
        <img id="image"/>
        <div id="name"></div>
        <a href="#" id="logout" onclick="userLogout()">Cerrar sesión</a> <br />
        <a href="#" id="publish" onclick="publishStream()">Publicar en el muro</a> <br />
        <a href="#" id="request" onclick="requestDialog()">Invitar a amigos</a>
    </div>

Simplemente es un contenedor div, por defecto oculto, que mostrará una imagen, el nombre del usuario, y tres enlaces.

Vamos a por el nuevo código JavaScript que hemos añadido:

        FB.Event.subscribe('auth.login', function () {
            window.location.reload();
        });

        FB.Event.subscribe('auth.logout', function (response) {
            window.location.reload();
        });

        FB.getLoginStatus(function(response) {
            if (response.authResponse) {
                document.getElementById('fb-login-button').style.display = 'none';
                document.getElementById('user-box').style.display = 'block';
                FB.api('/me', function(user) {
                    if(user != null) {
                        var image = document.getElementById('image');
                        image.src = 'https://graph.facebook.com/' + user.id + '/picture';
                        var name = document.getElementById('name');
                        name.innerHTML = user.name
                    }
                });
            }
        });

        function userLogout() {
            FB.getLoginStatus(function(response) {
                if (response.authResponse) {
                    FB.logout();
                }
            });
        }

        function publishStream() {
            var body = 'Probando la demo del SDK de JavaScript de Facebook';
            FB.api('/me/feed', 'post', { message: body }, function(response) {
                if (!response || response.error) {
                    alert('Ha ocurrido un error');
                } else {
                    alert('¡Éxito! Entra a tu muro y verás una nueva publicación');
                }
            });
        }

        function requestDialog() {
            FB.ui({
                method: 'apprequests',
                message: 'Echa un vistazo a esta demo.',
                title: 'Compartir aplicación'
            });
        }

Paso a paso:

  1. En primer lugar llamamos a FB.Event.subscribe para que cuando el usuario inicie sesión (es decir, cuando se lance el evento auth.login), la página se recargue.
  2. Del mismo modo, cuando el usuario cierre sesión (cuando se lance el evento auth.logout), la página también se recargará.
  3. Después invocamos a FB.getLoginStatus. Como vimos, con este método podemos saber si el usuario ha iniciado sesión y está conectado con nuestra aplicación, en función de si el objeto authResponse está o no presente. En ese caso de que lo esté (está conectado):
    1. Ocultamos el Login Button
    2. Mostramos el div contenedor.
    3. Realizamos una llamada a la API (FB.api) consultando información sobre el usuario activo. Construimos la URL de su avatar y lo establecemos a la imagen que hay dentro del div contenedor. E igualmente, extramos su nombre completo y lo escribimos en el div con id ‘name’.
  4. Ahora definimos la función userLogout() que se invoca al hacer clic sobre el texto “Cerrar sesión”. Comprobará si se ha iniciado sesión, y en caso afirmativo, la cierra (FB.logout).
  5. La función publishStream se ejecuta cuando se hace clic sobre el texto “Publicar en el muro”. Mediante FB.api, realiza una llamada al método ‘/me/feed’ del Graph API, usando una petición POST, y con el mensaje de ‘body’. Tras realizar la petición, se le notifica al usuario de si se ha publicado con éxito o no la historia.
  6. Por último, definimos la función requestDialog, que se invoca al hacer clic sobre “Invitar a amigos”. Esta función realiza una llamada a FB.ui, pasándole tres parámetros (nombre del diálogo, texto de la petición, título de la petición), y genera el diálogo Request que permite enviar una invitación a los amigos para que usen la aplicación.

Ver demo completa.

Resumen

Hasta ahora ya conocíamos por encima todo el ecosistema de tecnologías para desarrollar en Facebook, y habíamos creado una primera aplicación que hacía uso de algunos Social Plugins y de Open Graph.

Esta vez ya nos hemos ensuciado más las manos. Hemos instanciado un nuevo Social Plugin (el Login Button), que nos ha generado el diálogo OAuth, con el que hemos podido solicitar determinados permisos para nuestra aplicación. Después hemos revisado los principales métodos del SDK JavaScript, y hemos visto cómo muchos de esos métodos ya estaban funcionando incluso sin invocarlos nosotros a manos. Después hemos puesto en práctica nuestro conocimiento del SDK: nos hemos atado a eventos generados por Facebook (auth.login y auth.logout), permitimos mostrar diferente contenido en función de si se ha iniciado o no sesión, consultamos en la API y mostramos información básica del usuario, hemos visto cómo cerrar sesión, cómo publicar en el muro del usuario directamente, y hemos creado un diálogo Request para invitar a nuestros amigos a usar la aplicación.

No está mal, ¿no? Con lo que ya conocemos, y un poco de imaginación, podemos crear aplicaciones muy ricas en funcionalidades. Pero todavía nos quedan algunas cosas por ver en esta serie introductoria a la programación en Facebook: cómo crear aplicaciones canvas, y cómo manejar el PHP SDK. Nos vemos en la siguiente parte y, como siempre, ¡gracias por leer!