Trabajando con la API de Mozilla Persona

He desarrollado a modo de ejemplo una aplicación sencilla escrita en jQuery y PHP para trabajar con la API de JavaScript de Mozilla. El proyecto aún se encuentra en fase beta, por lo que hay que tener en cuenta que esta API puede sufrir cambios.

En el artículo anterior expliqué brevemente el funcionamiento y los objetivos de Mozilla Persona, ahora voy a entrar en detalle sobre como trabajar con la API que han desarrollado en JavaScript. Utilizaré un ejemplo muy básico escrito en jQuery (para trabajar con las funciones de Persona y enviar los datos al backend) y PHP (para gestionar los resultados enviados por medio de AJAX y las sesiones de usuario). En Gihub podéis encontar el repositorio con todos los archivos de esta aplicació n, la cual consta de un fichero index.php por donde se accede a ésta y que es el encargdo de llamar a la vista, el fichero view.phtml; un fichero ajax_controller.php que gestiona las peticiones AJAX; y el directorio js que contiene la libreria jQuery y el archivo file.js que llama a la funciones de la API de Persona.

Voy a seguir el pequeño tutorial publicado por Mozilla donde explican paso a paso la implementación de su API resumida en 5 puntos:

1. Llamada a la librería de Persona

Lo primero que tenemos que hacer es llamar al archivo include.js desde nuestra vista. Esto es fácil:

<!-- view.phtml -->
<script src="https://login.persona.org/include.js"></script>

Esta llamada siempre será necesaria mientras los navegadores no implementen la API de forma nativa. Por cierto, nos avisan de que no debemos alojar este fichero en nuestro servidor, ya que puede sufrir cambios.

2. Añadir lo botones de login y logout

Para abrir el formulario de acceso a Persona y para cerrar la sesión deberemos llamar a las funciones navigator.id.request() y navigator.id.logout(), respectivamente. El ejemplo en jQuery es sencillo:

// js/file.js

$('#login').click(
    function(event)
    {
        event.preventDefault();
        navigator.id.request();
    }
);
$('#logout').click
(
    function(event)
    {
        event.preventDefault();
        navigator.id.logout();
    }
);

Comentar también tambien que se ha abierto un espacio para poder descargar las imágenes del botón de acceso.

3. Escuchar la respuesta login / logout

Una vez que el usuario ha introducido los datos en el formulario de acceso, la ventana de diálogo de Persona se cerrará devolviendo la vista a nuestra página. Gracias a la función navigator.id.watch() podremos saber la respuesta de Persona (login o logout). Está función requiere de tres parámetros:

  • loggedInUser: variable que podrá tener dos valores: un string con el email del usuario (en caso de tener ya abierta una sesión en Persona) o null, en caso de que el usuario aún no no esté logueado.

  • onlogin: función que se ejecuta cuando el usuario abre una nueva sesión. A esta función se le pasa el parámetro "assertion", el cual deberemos verificar en nuestro backend.

  • onlogout: función que se ejecuta cuando el usuario ha cerrado la sesión.

De forma similar al ejemplo publicado por Mozilla, ambas funciones hacen una petición POST a nuestro backend (en este caso al fichero ajax_controller.php), donde abriremos/cerraremos la sesión de usuario (en el punto 4 veremos esto). Una vez que se ha recibido la respuesta, se recarga la página para mostrar el nuevo estado del usuario.

Seguimos con el fichero file.js, al que le añadimos las siguientes líneas:

navigator.id.watch
(
    {
        loggedInUser: user_email,
        onlogin: function(assertion)
        {
            $.post
            (
                'ajax_controller.php',
                {
                    action: 'login',
                    assertion: assertion
                },
                
function(
response, status)
                {
                    if (status == 'success') {
                        window.location.reload();
                    }
                }
            );
        },
        onlogout: function()
        {
            $.post
            (
                'ajax_controller.php',
                {
                    action: 'logout'
                },
                function(response, status)
                {
                    if (status == 'success') {
                        window.location.reload();
                    }
                }
            );
        }
    }
);

Por seguridad, debemos siempre gestionar el parámetro assertion en nuestro backend nunca en el js.

Persona comparará la dirección de e-mail que se le ha pasado a la variable loggedInUser, con aquella existente para el usuario logueado, si existe. En este ejemplo vemos que loggedInUser recibe el valor user_email, el cual es definido en la vista pudiendo tomar dos valores (null o el email del usuario logueado).

4. Comprobar las credenciales del usuario

En el fichero ajax_controller.php (se muestra al final de este punto) gestionamos el login y el logut. Para el segundo simplemente se trata de destrutir la sesión previamemte abierta.

En el caso del login recibimos vía $_POST la variable assertion que utilizaremos para verificar la validez del usuario junto con la dirección de nuestro propio dominio. Ambos valores se pasan como parámetos ("assertion" y "audience", respectivamente) a la url https://verifier.login.persona.org/verify la cual es analizada por medio de la librería cURL de PHP.

Para poder analizar el resultado de la respuesta (json), la decodifico por medio de la función json_ decode de PHP quedando un array similar a esto:

array(
    [status] => okay
    [email] => email_del_usuario_registrado
    [audience] => url_dominio_web
    [expires] => 1352309452358
    [issuer] => login.persona.org
)

Vemos que disponemos de 5 variables:

  • status: estado de la respuesta: "okay" o "failure". En caso de "failure" solo se nos devolverá el parámetro "reason" donde se explica el fallo de la verificación.

  • email: dirección de correo de la persona que está accediendo

  • audience: url de nuestro dominio

  • expires: fecha en la que expirará la variable assertion expresada en milisegundos (desde el 1 de enero de 1970)

  • issuer: nombre del proveedor de identidad

Si el status es "okay", significa que todo ha ido bien y ya podemos abrir una sesión. En mi ejemplo he abierto también una sesión para la dirección de correo electrónico del usuario. De esta manera la puedo pintar en la vista y así dar el valor a la variable loggedInUser de la API.

// ajax_controller.php

<?php
session_start();
if ($_POST['action'] == 'login') {
    $options = array(
        CURLOPT_URL => 'https://verifier.login.persona.org/verify',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => 2,
        CURLOPT_POSTFIELDS => 'assertion='.$_POST['assertion'].
        '&audience='.urlencode('http://'.$_SERVER['HTTP_HOST'])
    );
    $ch = curl_init();
    curl_setopt_array($ch, $options);
    $result = json_decode(curl_exec($ch), true);
    curl_close($ch);
    if ($result['status'] === 
'okay') {
      
  $_SESSION['logged'] = true;
        $_SESSION['email'] = $result['email'];
    }
} else if ($_POST['action'] == 'logout') {
    unset($_SESSION['logged']);
}

5. Revisar las buenas prácticas

Y para terminar, en este útimo punto desde Mozilla nos recomendan echar un vistazo a los consejos de seguridad resumidos en este artículo.

Comments

You must sing in to post a comment.

There are no comments for this article.