Windows Phone 7 – Tutorial XXXII–Seguridad VI–Autenticación OAuth

En la actualidad redes sociales como Twitter o Facebook están implementando la autenticación OAuth (Open Authorization) para las aplicaciones externas, de manera que si desarrollamos un cliente Twitter nuestra aplicación deberá autenticarse mediante este método. En este artículo vamos a ver como realizar esta autenticación contra Twitter que utiliza autenticación Oauth1.0.

La manera de autenticarse con OAuth es a través de una pagina web que nos proporciona en este caso Twitter donde el usuario se autenticará con su cuenta de Twitter, una vez autenticado esta página web nos mostrará un PIN que será el token que deberemos coger y utilizar para todas las llamadas que utilicemos para esa cuenta de Twitter, como podréis suponer esto lo tendremos que realizar a través de un control webbrowser, pero bueno esto lo veremos mas adelante.

Lo primero que tendremos que hacer es crear una cuenta de desarrollador en Twitter, para ello iremos al sitio http://dev.twitter.com

 

image

image

 

Debemos elegir en tipo de aplicación Client, esto es importante porque cuando el usuario se autentique en la web que le presentará twitter debemos de recoger el PIN que le asigne.

image

En esta ultima ventana tenemos ConsumerKey y ConsumerSecret que tendremos que utilizar en nuestra aplicación y luego nos enseñan las url necesarias para autenticarnos

image

Cuando el usuario utilice nuestra aplicación en Windows Phone 7 deberá seguir estos pasos para autenticarse

 

twiiter_HomeScreentwitter_startScreenimagetwitter_signIn_2tiwtter_authorize

Bueno empezamos a desarrollar nuestra conexión a Twitter, para ello crearemos nuestra aplicación a la que llamaremos AutenticacionOAuthTwitter. En nuestra pagina Main insertaremos un botón y un navegador, dentro del botón nos subscribiremos al evento Click para empezar la autenticación. No lo vamos a realizar con MVVM para que sea mas sencillo entenderlo.

Para entender los siguientes pasos yo recomiendo leer la pagina de Twitter en la que explica como se realiza la autenticación paso a paso, podeis acceder desde esta dirección http://dev.twitter.com/pages/auth

Lo primero que vamos a hacer es crear la clase OAuthAuthenticate que se encargara de toda la autenticación, esta clase tendrá las propiedades

1 public class OAuthAuthenticate 2 { 3 public string RequestUri { get; set; } 4 public string AuthorizeUri { get; set; } 5 public string AccessUri { get; set; } 6 7 public string Method { get; set; } 8 9 public string NormalizedUri { get; set; } 10 public string NormalizedParameters { get; set; } 11 12 public string VerifierPin { get; set; } 13 14 public string ConsumerKey { get; set; } 15 public string ConsumerSecret { get; set; } 16 public string Token { get; set; } 17 public string TokenSecret { get; set; } 18 19 public IDictionary<string, string> Parameters { get; private set; } 20 }

En estas propiedades guardaremos las uri de acceso a la autenticación, autorización.. que nos ha proporcionado Twiiter, el método de paso de parámetros si es POST o GET , nuestros ConsumerKey y ConsumerSecret…., además de un diccionario donde guardaremos los parámetros que nos devuelva Twitter cuando pedimos el Token.

 

En nuestro caso las inicializaremos con 

 

1 RequestUri = "https://api.twitter.com/oauth/request_token", 2 AuthorizeUri = "https://api.twitter.com/oauth/authorize", 3 AccessUri="https://api.twitter.com/oauth/access_token", 4 Method = "POST", 5 ConsumerKey = "Tu ConsumerKey", 6 ConsumerSecret = "Tu ConsumerSecret"

Ahora crearemos nuestro método de autenticación al que le pasaremos dos parámetros el objeto browser donde el usuario va a realizar la autenticación y un objeto callback para que una vez producida la autenticación por ejemplo hagamos invisible el navegador. La firma sería la siguiente.

public void Authenticate(WebBrowser browser, Action<IDictionary<string, string>> callback)

 

Lo primero que  debemos hacer es recoger el token de petición que Twitter nos proporciona, para ello utilizamos la uri de la propiedad RequestUri a través de una petición HttpWebRequest, esta petición tal como nos indica la documentación de Twitter debe de ir con una serie de parámetros en el que se indica la versión de OAuth que utilizamos, el TimeStamp, si utilizamos HMACSHA1… esto lo realizaremos en el método

 

1 public static string GenerateSignature(this OAuthRequest request, string uri) 2 { 3 if (!string.IsNullOrEmpty(request.Token)) 4 { 5 request.Parameters[OAuthTokenKey] = request.Token; 6 } 7 8 if (!string.IsNullOrEmpty(request.VerifierPin)) 9 { 10 request.Parameters[OAuthVerifierKey] = request.VerifierPin; 11 } 12 13 request.Parameters[OAuthConsumerKeyKey] = request.ConsumerKey; 14 request.Parameters[OAuthVersionKey]=OAuthVersion; 15 request.Parameters[OAuthNonceKey]=GenerateNonce(); 16 request.Parameters[OAuthTimestampKey]=GenerateTimeStamp(); 17 request.Parameters[OAuthSignatureMethodKey]=HMACSHA1SignatureType; 18 request.Parameters[OAuthConsumerKeyKey]=request.ConsumerKey; 19 20 string signatureBase = GenerateSignatureBase(request, uri); 21 22 HMACSHA1 hmacsha1 = new HMACSHA1(); 23 hmacsha1.Key = Encoding.UTF8.GetBytes(string.Format("{0}&{1}", UrlEncode(request.ConsumerSecret), string.IsNullOrEmpty(request.TokenSecret) ? "" : UrlEncode(request.TokenSecret))); 24 25 var signature = ComputeHash(signatureBase, hmacsha1); 26 request.Parameters[OAuthSignatureKey] = UrlEncode(signature); 27 return signature; 28 } 29

 

1 public void RetrieveRequestToken(Action Callback) 2 { 3 this.GenerateSignature(this.RequestUri); 4 5 var request = HttpWebRequest.Create(this.NormalizedUri); 6 request.Method = this.Method; 7 request.Headers[HttpRequestHeader.Authorization] = this.GenerateAuthorizationHeader(); 8 9 request.BeginGetResponse((result) => 10 { 11 var req = result.AsyncState as HttpWebRequest; 12 var resp = request.EndGetResponse(result) as HttpWebResponse; 13 14 using (var strm = resp.GetResponseStream()) 15 using (var reader = new StreamReader(strm)) 16 { 17 var responseText = reader.ReadToEnd(); 18 this.ParseKeyValuePairs(responseText); 19 } 20 21 Callback(); 22 23 }, request); 24 25 } 26

 

 

1 public void Authenticate(WebBrowser browser, Action<IDictionary<string, string>> callback) 2 { 3 var baseAuthorizeUri = this.AuthorizeUri; 4 browser.Navigated += (s, e) => 5 { 6 if (e.Uri.AbsoluteUri.ToLower().StartsWith(baseAuthorizeUri)) 7 { 8 if (!e.Uri.Query.Contains("oauth_token")) 9 { 10 var htmlString = browser.SaveToString(); 11 12 var authPinName = "oauth_pin>"; 13 var startDiv = htmlString.IndexOf(authPinName) + authPinName.Length; // eg <DIV id=oauth_pin>4697728</DIV></DIV> 14 var endDiv = htmlString.IndexOf("<", startDiv); 15 var pin = htmlString.Substring(startDiv, endDiv - startDiv); 16 17 this.VerifierPin = pin; 18 this.RetrieveAccessToken(callback); 19 } 20 } 21 }; 22 23 // Obtener el token 24 RetrieveRequestToken(() => 25 { 26 browser.Dispatcher.BeginInvoke(() => 27 { 28 browser.Navigate(new Uri(this.AuthorizeUri)); 29 }); 30 }); 31 } 32


Ya solo nos queda un paso y es recoger el token de acceso a tarves de la uri de acceso que nos indica Twitter, si os fijáis en el evento OnNavigated la ultima instrucción es RetrieveAccessToken que recogera el token de acceso, que es muy parecido al método RetriveRequestToken de antes.

1 public void RetrieveAccessToken(Action<IDictionary<string, string>> Callback) 2 { 3 4 5 this.GenerateSignature(this.AccessUri); 6 7 var request = HttpWebRequest.Create(this.NormalizedUri); 8 request.Method = this.Method; 9 request.Headers[HttpRequestHeader.Authorization] = this.GenerateAuthorizationHeader(); 10 request.BeginGetResponse((result) => 11 { 12 var req = result.AsyncState as HttpWebRequest; 13 var resp = request.EndGetResponse(result) as HttpWebResponse; 14 15 Dictionary<string, string> responseElements; 16 17 using (var strm = resp.GetResponseStream()) 18 using (var reader = new StreamReader(strm)) 19 { 20 var responseText = reader.ReadToEnd(); 21 responseElements = this.ParseKeyValuePairs(responseText); 22 } 23 24 Callback(responseElements); 25 26 }, request); 27 28 } 29 } 30 }

Una vez seguidos estos pasos ya tenemos nuestra autenticación en Twitter, deberemos grabar estos valores en el IsolatedStoraged para que el usuario no tenga que volverse a identificar cada vez que arranque la aplicación.

Si queréis hacer una aplicación para Twitter os recomiendo utilizar TweetSharp que os va a abstraer de la comunicación con la api de Twitter, este articulo ha sido para que entendais la forma de comunicarnos con un sistema con autorización OAuth.