Al parecer OAuth está últimamente arrasando en cuando a protocolos de autenticación se refiere, y ya lo están utilizando Google, Twitter, y Facebook, entre otros muchos.
Graph API utiliza OAuth 2.0 como método de autenticación basado en el intercambio de tokens. Como ya comentamos en la segunda parte de este post, lo primero que tenemos que hacer para recuperar cualquier tipo de dato de las entrañas de Facebook (posts, imágenes, información de usuarios) es obtener un access token público. Una vez obtenido ese token, podremos solicitar un access token privado, con el que el usuario podrá interactuar con Facebook. La recuperación de este token privado implica los siguientes pasos:
- Obtención de un token público con el que poder instanciar un nuevo objeto de nuestro conector FacebookAPI (al que si os acordáis deberemos pasar el AppID y el AppSecret de nuestra aplicación residente en FB).
- Solicitud de un access token privado, mediante redirección a la página de autenticación de Facebook (en donde el usuario introducirá su login y password) pasándole por parámetro el token público que ya tenemos.
- Redirección por parte de Facebook, y sólo en caso de éxito en el login, a la página configurada en la Postback Url de la aplicación residente en FB, en donde se nos pasa por parámetro un código para intercambiar por el access token privado.
- Obtención de un token privado al intercambiarlo por el código devuelto.
- Una vez tenemos el nuevo access token privado, podemos desechar el público y utilizar éste, que nos permitirá realizar llamadas POST sobre el objeto FacebookAPI para postear datos, o simplemente poder obtener los comentarios de los posts en el muro.
Como véis, éste método tiene 2 claras ventajas:
- Delega en Facebook la crítica parte de login/password que siempre nos puede traer de cabeza, y...
- Nos proporciona un token con una vida de 60 minutos que tendremos que incluir en cada llamada a Facebook, y con el que tendremos acceso al mundo Facebook.
Genial, ¿no? Pues vamos con un poco de código.
En el botón estilo "Connect with Facebook" manejamos el evento del click generando una URL de autenticación del estilo https://graph.facebook.com/oauth/client_id=[]& redirect_uri=[]&scope=publish_stream,read_stream.
///
/// Handles the Click event of the btConnect control.
///
/// The source of the event.
/// Theinstance containing the event data.
protected void BtConnectClick(object sender, EventArgs e)
{
var api = new FacebookAPI(this.Token);
var authParameters = new Dictionary
{
{ "client_id", AppId },
{ "redirect_uri", PostbackUrl },
{ "scope", "publish_stream,read_stream" }
};
var urlConnect = api.GetAuthorizeUrl(authParameters);
this.Response.Redirect(urlConnect.AbsoluteUri, true);
}
Si el usuario autoriza realiza el login con éxito y autoriza la aplicación, Facebook redirige al usuario de vuelta con un código que utilizaremos para intercambiar por el token privado. Este intercambio lo realizaremos mediante llamando a nuestro método sobrecargado GetAccessToken, esta vez con más parámetros que en la parte 2 de este post.
///
/// Gets the access token for authenticated users.
///
/// The app id.
/// The app secret.
/// The redirect URL.
/// The app code from callback.
///Authenticated access token.
public static string GetAccessToken(string appId, string appSecret, string redirectUrl, string appCodeFromCallback)
{
if (string.IsNullOrEmpty(appId) || string.IsNullOrEmpty(appSecret) || string.IsNullOrEmpty(redirectUrl) ||
string.IsNullOrEmpty(appCodeFromCallback))
{
return null;
}
var url =
string.Format(
"https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&client_secret={2}&code={3}&req_perms=publish_stream",
appId,
redirectUrl,
appSecret,
appCodeFromCallback);
string accessTokenValue = null;
var request = WebRequest.Create(url) as HttpWebRequest;
try
{
if (request != null)
{
using (var response
= request.GetResponse() as HttpWebResponse)
{
if (response != null)
{
var reader
= new StreamReader(response.GetResponseStream());
// access_token is the first of the parameters
accessTokenValue = reader.ReadToEnd();
accessTokenValue = accessTokenValue.Split(new[] { "&" }, StringSplitOptions.RemoveEmptyEntries)[0];
accessTokenValue = accessTokenValue.Replace("access_token=", string.Empty);
}
}
}
}
catch (WebException e)
{
throw new FacebookAPIException("Server Error", e.Message);
}
return accessTokenValue;
}
Con este access token privado podremos hacer llamadas como postear un nuevo mensaje en el muro de nuestro grupo de Facebook, a través de una llamada al método ya visto Call, pero de tipo POST.
///
/// Makes a Facebook Graph API POST request.
///
/// The path for the call,
/// e.g. /username
/// A dictionary of key/value pairs that
/// will get passed as query arguments. These determine
/// what will get set in the graph API.
///JSON object of the request.
public JSONObject Post(string relativePath, Dictionaryargs)
{
return this.Call(relativePath, HttpVerb.POST, args);
}
Y podremos gestionar el evento click del botón de postear un nuevo comentario así:
///
/// Handles the Click event of the btMessage control.
///
/// The source of the event.
/// Theinstance containing the event data.
protected void BtMessageClick(object sender, EventArgs e)
{
var api = new FacebookAPI(this.Token);
var url = string.Format("/{0}/feed", GroupId);
var postParameters = new Dictionary
{
{ "message", this.tbMessage.Text }
};
api.Post(url, postParameters);
}
Colgaré todo el código de esta mini-integración con la GraphAPI en un futuro, pero de momento aquí finaliza esta serie de posts.
Espero que os haya resultado interesante. En la mente tengo hacer algo del estilo para Android, aunque todavía queda mucho para eso, ufff...
Por supuesto cualquier otra idea será muy bien recibida :-)