[Windows Phone 8.1] WebAuthenticationBroker

Hola a todos!

Después de unos días sin escribir y de que se presentase oficialmente la RTM del SDK de Windows Phone 8.1, volvemos a la carga con novedades en las APIs de Windows Phone 8.1. En esta ocasión quiero hablar del WebAuthenticationBroker. Los que hayáis trabajado con apps Windows Store, lo conoceréis sin duda. Para el resto, aquí va una introducción.

¿Qué es el WebAuthenticationBroker?

El WebAuthenticationBroker es una clase pensada para facilitarnos la vida como desarrolladores a la hora de usar sistemas de autenticación OAuth de cualquier tipo. Facebook, Twitter, LinkedIn… casi toda empresa que expone APIs públicas usa OAuth como sistema de identificación. Básicamente este sistema nos permite registrar nuestra app en él y obtener unos identificadores para la misma. Luego, en tiempo de ejecución nuestra aplicación abre una web del sistema, enviando los identificadores recibidos a la misma y en la que se pide al usuario que introduzca su nombre y clave para autorizar a nuestra aplicación a acceder a su cuenta. Lo bueno de esto es que el usuario no introduce sus datos en nuestra aplicación, lo hace en una web del creador del API, por lo que su confianza debería ser mayor. Al final, nuestra aplicación recibe un token, normalmente con un tiempo de vida predeterminado, que podemos usar para autentificar las llamadas al API que realicemos. Además, el usuario puede revocarnos el acceso desde la administración del API en cualquier momento. A continuación os muestro un esquema, OAuth tiene un funcionamiento interno que en este esquema simplifico para enseñar como se relaciona con nuestra aplicación, no como funciona internamente que está fuera del alcance de este artículo:

image

Como podemos ver, simplemente hacemos una petición a una URL OAuth. En realidad navegamos a esa URL, lo cual muestra la web de autenticación. En el ejemplo he puesto una de las webs de autenticación que usa Facebook. En esa web, el usuario puede permitirnos el acceso a su cuenta. Si funciona correctamente, la web nos redirigirá a una URL de respuesta configurada en el servicio al registrar nuestra aplicación. En esa redirección, suele enviarse como parámetro el token de acceso a la API. Y listo, ya podemos realizar peticiones autenticadas con el token que hemos recibido.

¿Como implementamos esto antes de Windows Phone 8.1?

Pues muy a “mano”. Básicamente, siguiendo los siguientes pasos:

  • Construías en nuestra aplicación una página que contuviese un WebBrowser.
  • Si no estamos autenticados (no tenemos un token) navegar a la URL de OAuth en esa página
  • Vigilar los eventos de navegación del WebBrowser para detectar cuando esta redirigiéndonos a la respuesta.
  • Procesar la URL de respuesta para extraer el token.

No es que sea el proceso más complicado del mundo, pero es todo muy manual y puede llevarnos un rato de prueba/error si queremos que funcione con varios proveedores distintos al mismo tiempo.

¿Como implementamos esto ahora en Windows Phone 8.1?

Lo implementamos usando el WebAuthenticationBroker, que nos facilita la vida:

  • Si no estamos autenticados (no tenemos un token) llamamos al método AuthenticateAndContinue de la clase WebAuthenticationBroker.
  • Recibimos la respuesta y extraemos el token.

Si, ya está. Solo tenemos que hacer eso. El propio WebAuthenticationBroker se encarga por nosotros de todos los demás pasos. Esta fue una de las grandes novedades que incluyó Windows 8 en su API WinRT cuando salió y por fin la tenemos disponible en Windows Phone. No obstante existen ciertas diferencias entre el API de Windows 8 y la de Windows Phone 8.1, como veremos a continuación.

WebAuthenticationBroker: Windows Store vs Windows Phone

Como hemos dicho, solo tenemos que llamar al método AuthenticateAndContinue de la clase WebAuthenticationBroker, pero este método no existe en Windows Store, donde usaremos en su lugar AuthenticateAsync. Esta diferencia, que encontraremos en algunas APIs más de Windows Phone 8.1, va mas allá de un simple cambio de nombre. AuthenticateAsync es, como su nombre indica asíncrono, podemos usar await para esperar que se complete y nos de el resultado. Por el contrario, AuthenticateAndContinue no es asíncrono y devuelve ¡VOID!, ahora veremos porqué y como obtener el resultado.

El problema principal es el siguiente. En terminales de baja memoria, 512Mb, Windows Phone no puede asegurar en todo momento que pueda mantener nuestra aplicación abierta al mismo tiempo que lanza otra aplicación, la cual se encargará de realizar la autenticación. Por este motivo, ciertas APIs que necesitan abrir un “Broker”, una aplicación del sistema para realizar una acción, como el WebAuthenticationBroker, han implementado un método llamado “DoSomethingAndContinue” que no devuelve ningún resultado. En su lugar seguiremos el siguiente flujo:

image

Básicamente tenemos los siguientes pasos:

  1. Nuestra aplicación ejecuta el método AuthenticateAndContinue del WebAuthenticationBroker. En esta
  2. La aplicación WebAuhtenticationBroker del sistema pasa a primer plano y nuestra app se suspende. Dependerá del sistema si se conserva en memoria o no.
  3. El usuario realiza las acciones necesarias y el WebAuthenticationBroker termina, activando nuestra app de nuevo.
  4. Nuestra app pasa al primer plano, recibiendo como argumento un objeto de tipo AuthenticationResult.
  5. Tenemos que enviar la respuesta a nuestra página/viewmodel para seguir trabajando.

Viendo el código.

Ahora que tenemos claro como funciona el proceso, vamos a ver el código implicado en él. Para el primer paso, necesitaremos una URL de autenticación OAuth que podamos usar. En este ejemplo vamos a usar una de Facebook. Para obtener una URL, tendremos que ir a https://developers.facebook.com/, registrarnos y crear una nueva app en el menú superior “Apps”:

image

Una vez creada, nos mostrará la página de la app con el AppID y el AppSecret, estos identificadores serán necesarios para componer nuestra URL de conexión a continuación:

https://www.facebook.com/dialog/oauth?client_id=[APPID]&redirect_uri=http://localhost/reply&scope=[PERMISOS]&display=popup&response_type=token

Simplemente tenemos que sustituir el texto [APPID] por el appID que nos dio Facebook al registrar la aplicación y añadir los permisos necesarios, según las acciones que deseemos realizar.

El código sería algo como esto:

AuthenticateAndContinue
private void LoginFacebookExecute()
{
    string appID = “YOUR APP ID FROM FACEBOOK”;
    string permissions = “publish_actions”;
    string authUrl = string.Format(“https://www.facebook.com/dialog/oauth?client_id={0}&redirect_uri=http://localhost/reply&scope={1}&display=popup&response_type=token”, appID, permissions);
            
    WebAuthenticationBroker.AuthenticateAndContinue(new Uri(authUrl), new Uri(“http://localhost/reply”), null, WebAuthenticationOptions.None);
}

Como vemos no es un código complicado. formamos la URL de OAuth2 de Facebook añadiendo nuestro APPID y los permisos a usar y a continuación llamamos al método AuthenticateAndContinue. Es en esta parte donde viene lo divertido. Justo tras llamar a ese método, nuestra aplicación se suspende y se abre el WebAuthenticationBroker. ¿Y como obtenemos el resultado de la operación? Bien, controlando el método OnActivated de la clase App (App.xaml.cs) Desde ese método deberemos pasar la información a nuestra ViewModel. Para hacer esto más sencillo, yo he creado un Interface que añado a todas las ViewModels que hacen uso de métodos “…AndContinue”. Esta interface se llama IContinuationAwareViewModel y define el método Continue:

IContinuationAwareViewModel
public interface IContinuationAwareViewModel
{
    void Continue(IActivatedEventArgs args);
}

Simplemente la implemento en la ViewModel donde hemos llamado a AuthenticateAndContinue y dentro del método Continue pongo el código para recibir y procesar la respuesta de Facebook:

Continue
public void Continue(IActivatedEventArgs args)
{
    var arguments = (WebAuthenticationBrokerContinuationEventArgs)args;
    WebAuthenticationResult result = arguments.WebAuthenticationResult;

    if (result.ResponseStatus == WebAuthenticationStatus.Success)
    {
        string responseCode = result.ResponseData;
        responseCode = responseCode.Substring(responseCode.IndexOf(“=”) + 1);
        AccessToken = responseCode.Split(‘&’).First();
        ExpirationTime = int.Parse(responseCode.Split(‘&’).Last().Split(‘=’).Last());
    }
}

Comprobamos si la operación a tenido éxito y simplemente procesamos la cadena de texto que devuelve Facebook con el token de acceso y el tiempo de expiración en segundos.

Ahora ya solo nos queda ver como invocar a este método desde el OnActivated de la clase App:

App OnActivated
protected override void OnActivated(IActivatedEventArgs args)
{
    var rootFrame = (Frame)Window.Current.Content;
    var currentPage = (Page)rootFrame.Content;
    var currentViewModel = (IContinuationAwareViewModel)currentPage.DataContext;

    currentViewModel.Continue(args);
}

Primero obtenemos el frame actual de la aplicación, del cual extraemos la página activa. Del DataContext de la página extraemos la ViewModel (que convertimos a IContinuationAwareViewModel) y ya solo nos queda invocar al método Continue pasando los argumentos de activación. Es tarea del método Continue implementado en la ViewModel decidir como usar esos argumentos y que información obtener. De esta forma, si tenemos varias páginas que usen métodos “…AndContinue” el método de activación será standard para todas ellas.

Y con esto llegamos al final de esta artículo. Como siempre, aquí tienes el ejemplo funcionando con el código que hemos visto, para que puedas jugar con él y por supuesto usando MVVM para que veas como implementar WebAuthenticationBroker con todas las piezas en su sitio.

Espero que lo disfrutes.

Un saludo y Happy Coding!

 

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *