lunes, 1 de febrero de 2010

OpenID con PHP









Vamos a implementar OpenID en nuestra web utilizando la librería PHP OpenID Library de JanRain Inc.. En base a nuestro propio sistema de usuarios daremos la posibilidad de hacer login en nuestra web utilizando una cuenta OpenID.



Este artículo es un resumen/traducción del artículo original en inglés Getting Started with OpenID and PHP



Descargamos PHP OpenID Library, para este articulo se ha usado la versión 2.1.1. Luego descomprimimos la carpeta Auth en la raíz de nuestra web.



Nuestra base de datos para almacenar la información de los usuarios tendrá este aspecto

000

001

002

003

004

005

006

007

CREATE TABLE `usuarios` (

`id` int(11) NOT NULL auto_increment,

`nick` varchar(15) NOT NULL,

`pass` varchar(32) NOT NULL,

`email` varchar(100) NOT NULL,

`zodiaco` varchar(15) NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=MyISAM;
Nota:

El campo zodiaco se me ha ocurrido como un dato de nuestra DB que OpenID no nos proporciona. Descarga los archivos de ejemplo para ver porque lo he utilizado




Utilizamos un formulario básico de login en HTML

000

001

002

003

004

005

006

007

008

009

010

011

012

<h1>Conectar usuario</h1>

<form method="post" action="login.php">


<p><input type="text" name="usuario" value="Usuario" /></p>

<p><input type="password" name="pass" value="Contraseña" /></p>

<p><input type="submit" name="enviar" value="Enviar" /></p>

</form>



<h1>Conectar con OpenID</h1>

<form method="post" action="openid.php">

<p><input type="text" name="openid" value="http://" /></p>

<p><input type="submit" name="enviar" value="Enviar" /></p>

</form>




Como ves hay dos formularios. El primero es el clásico formulario con usuario/contraseña. Este formulario envía los datos al archivo login.php que contiene las rutinas generales para autentificar a un usuario. Esto no lo veremos en este articulo pero si en el ejemplo para descargar. El segundo es el formulario de OpenID. Solicita la URL de una cuenta OpenID y envía los datos al archivo openid.php del cual hablamos ahora.



openid.php realiza la petición de autentificación al servidor OpenID

000

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

034

035

036

037

038

039

if (isset($_POST["openid"])) {

trim($_POST['openid'] == '');



// incluir dependencias

require_once "Auth/OpenID/Consumer.php";

require_once
"Auth/OpenID/FileStore.php";

require_once
"Auth/OpenID/SReg.php";

include
'config.php';



// iniciar sesión (necesario para YADIS)


session_start();



// directorio de almacenamiento de OpenID

$almacenamiento = new Auth_OpenID_FileStore('./oid_store');



// crear el cliente OpenID

$cliente = new Auth_OpenID_Consumer($almacenamiento);



// Inicia el proceso de autentificación y crea las peticiones para el servidor OpenID

$auth = $cliente->begin($_POST['openid']);

if (!
$auth) {

die(
'No se ha podido conectar al servidor OpenID');

}



// petición para obtener los datos de usuario


$sreg = Auth_OpenID_SRegRequest::build(array('email', 'fullname'), array('nickname'));

if (!
$sreg) {

die(
'no se ha podido obtener la información de usuario');

}

$auth->addExtension($sreg);



// redireccionar al servidor OpenID para autentificar la cuenta

$url = $auth->redirectURL($web, $openid_return);

header('Location: ' . $url);

}else {

// Si no hay post redireccionamos al formulario de login

header('location: conectar.php');

}

?>


Destacamos algunas partes importantes del archivo openid.php.



$almacenamiento = new Auth_OpenID_FileStore('./oid_store');

Debemos crear un directorio donde OpenID almacena información necesaria para su funcionamiento. Simplemente crea este directorio y dale permisos de escritura. En este caso, el directorio se llama oid_store



$sreg = Auth_OpenID_SRegRequest::build(array('email', 'fullname'), array('nickname'));

Indicamos la información que queremos obtener de la cuenta de usuario OpenID. Se establece que nickname es un campo obligatorio que el usuario debe tener en su cuenta openID y como opcionales indicamos el email y nombre completo. Otros datos opcionales que podemos obtener son la fecha de nacimiento, país, lenguaje, código postal y zona horaria. Cada uno tiene su propio codigo, así la fecha de nacimiento se indica con dob, el pais con country o el lenguaje con language



$url = $auth->redirectURL($web, $openid_return);

El primer parametro establece la URL de nuestra web y el segundo parámetro la URL del archivo donde finalizará el proceso de autentificación. El archivo openid_return.php será donde el servidor OpenID redigirá al usuario después de verificar su cuenta OpenID, por lo tanto, este archivo es de vital importancia y es nuestra próxima parada en este artículo. las variables $web y $openid_return las podrás ver en el archivo config.php



openid_return.php finaliza el proceso de autentificación, nos indica si se ha realizado login en el servidor OpenID y nos devuelve la información de la cuenta OpenID.

000

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

034

035

036

037

038

039

040

041

042

043

044

045

046

047

048

049

050

051

052

053

054

055

056

057

058

059

060

061

062

063

// incluir archivos

require_once "Auth/OpenID/Consumer.php";

require_once
"Auth/OpenID/FileStore.php";

require_once
"Auth/OpenID/SReg.php";

include
'config.php'; // contiene datos de conexión a nuestra base de datos MySQL



// iniciar sesión (necesario para YADIS y para nuestro sistema de autentificación)

session_start();



// directorio de almacenamiento OpenID

$almacenamiento = new Auth_OpenID_FileStore('./oid_store');



// crear el cliente OpenID y leer las respuestas del servidor OpenID

$cliente = new Auth_OpenID_Consumer($almacenamiento);

$respuesta = $cliente->complete($openid_return);



// establecer las variables de sesión dependiendo del resultado de la autentificación

if ($respuesta->status == Auth_OpenID_SUCCESS) {

$_SESSION['OPENID_AUTH'] = true; // autentificación correcta



// obtener los datos del usuario en su cuenta OpenID

$sreg = new Auth_OpenID_SRegResponse();

$obj = $sreg->fromSuccessResponse($respuesta);

$info = $obj->contents(); // $info["email"], $info["nick"], $info["fullname"]....

// print_r($info);



if ($info["email"]) {

// comprobamos si el email existe en nuestra base de datos, en tal caso, el usuario ya tiene una

// cuenta en nuestra web y establecemos las variables de sesión

$sql = mysql_query("SELECT nick FROM usuarios WHERE email='".$info["email"]."'");

if (
mysql_num_rows($sql)) {

$sql_ok=mysql_fetch_array($sql);

$_SESSION["sLogin"] = true;

$_SESSION["sNick"] = $sql_ok["nick"];

die(
'Bienvenido a casa. Accede a la zona restringida');

}else {

// si el email no existe en nuestra BD se trata de un nuevo usuario. Tendremos que mostrar al

// usuario un formulario de registro para que inserte los datos de su cuenta que OpenID no proporciona.

// por ejemplo, podriamos necesitar en nuestra base de datos la direccion postal de nuestros usuarios,

// ya y que OpenID no proporciona este dato lo deberemos solicitar.

$_SESSION["nuevoOID"] = true;

$_SESSION["oidNick"] = ($info["nickname"]) ? $info["nickname"] : '';

$_SESSION["oidEmail"] = ($info["email"]) ? $info["email"] : '';

// en el formulario de registro de nuevo usuario establecemos por defecto los datos del usuario

// que recibimos con OpenID como pudieran ser el nick, el email, el nombre completo...

// para ello creamos las sesiones que contendrán estos datos.

// En este formulario indicaremos al usuario que seleccione su signo del zodiaco como un

// dato complementario que OpenID no proporciona y que necesitamos para nuestra web

header ('location: formulario-registro.php');

}



}else {

// OpenID no ha devuelto una dirección de email, en nuestro sistema de usuarios es imprescindible.

die('OpenID no ha devuelto tu dirección de email. Es necesario que establezcas tu email en tu cuenta OpenID para hacer uso de OpenID en nuestra web.');

}



} else {

// el servidor OpenID ha devuelto una autentificación fallida

$_SESSION['OPENID_AUTH'] = false;

die(
'La autentificación OpenID ha fallado. Inténtalo de nuevo');

}



?>


Como podemos ver en los comentarios de openid_return.php, una vez hemos autentificado con OpenID, en la mayoría de casos, deberemos comprobar si es la primera vez que el usuario utiliza OpenID para acceder a nuestra web, en tal caso deberemos solicitar al usuario que complete los datos de su cuenta en nuestra web. Si nuestra base de datos de usuarios únicamente contiene los campos nick, password e email posiblemente no tengamos que solicitar al usuario otros datos ya y que OpenID nos proporciona éstos (excepto el pass que no tiene porque ser necesario), pero si nuestra base de datos fuera la de una tienda online, por ejemplo, deberemos solicitar al usuario algunos datos que OpenID no nos proporciona, como la dirección postal, el teléfono... etc. Para este caso, he utilizado el campo zodiaco el cual deberá completarse al realizar login por primera vez con OpenID. No obstante, aunque nuestra base de datos únicamente contuviera los campos nick, email y password, podría darse la posibilidad de que el usuario no tuviera establecido un nick en su cuenta OpenID y deberiamos solicitarlo o, aunque tuviera nick, podríamos dar la posibilidad de utilizar un nick diferente en nuestra web.



Como podrás imaginar, en el proceso de autentificación podríamos realizar diferentes opciones dependiendo de nuestra base de datos y de las funcionalidades de nuestra web. Un ejemplo podría ser sourceforge.net. En este articulo no hemos necesitado conocer un password para los usuarios que realizan login con OpenID, pero en sourceforge.net si que solicitan una contraseña la primera vez que realizas login con OpenID debido a que sourceforge.net tiene servicios NO basado en web, como CVS, que requieren una contraseña para ser usados. Haz la prueba, accede a sourceforge.net y haz login con tu OpenID



Así pues, el proceso de autentificación no funciona en base a unos criterios generales sino a la propia funcionalidad de tu web y tu base de datos de usuario. Recuerdo que este articulo se ha escrito suponiendo que tenemos un sistema de usuarios convencional en nuestra web.



Descargar

Descarga los archivos de ejemplo de este tutorial. Incluye los scripts PHP/HTML de este articulo y la versión 2.1.1 de la libreria PHP OpenID Library (solo carpeta Auth). Nota que aunque en esta descarga se ofrezca una copia de la carpeta Auth es necesario que descargues la libreria completa de JanRain Inc. para conocer más sobre ella.



Requisitos de PHP OpenID Library

Para poder hacer funcionar OpenID en nuestro servidor necesitamos lo siguiente:

PHP 4.3.0 o superior

Fsockets o la extensión CURL (preferible CURL)

Extensiones GMP o Bcmath de PHP (se recomienda GMP)

Extensión domxml de PHP

Otros requisitos (como PEAR DB) no son necesarios para este articulo.

Nota:

En sistemas windows la libreria PHP OpenID Library nos puede devolver un error como este:

Fatal error: Define Auth_OpenID_RAND_SOURCE as null to continue with an insecure random number generator. in D:\wamp\www\openid\pweb\Auth\OpenID\CryptUtil.php on line 52

Esto es debido a que esta libreria por defecto intenta utilizar la funcionalidad randomness de los sistemas UNIX para generar numeros aleatorios seguros. Para solucionarlo debemos dirigirnos al archivo Auth\OpenID\CryptUtil.php y cambiar la linea define('Auth_OpenID_RAND_SOURCE', '/dev/urandom'); por define('Auth_OpenID_RAND_SOURCE', null);




Como saber si nuestro servidor tiene todos los requisitos?

Cuando descargamos la PHP OpenID Library, podemos comprobar si nuestro servidor es apto para utilizar OpenID ejecutando el archivo detect.php. Dicho archivo se encuentra en el directorio openid > examples > consumer > detect.php. No incluido en la descarga de ejemplo.





Latest Releases

PHP OpenID Library

Version 1.2.3 (zip) (tar.bz2) (Docs) (Changes) 2007-04-26
Version 2.1.3 (zip) (tar.bz2) (Docs) (Changes) 2009-04-21

Python OpenID Library

Version 1.2.0 (tar.bz2) (tar.gz) (zip) (Docs) (Changes) 2006-12-08
Version 2.2.4 (tar.bz2) (tar.gz) (zip) (Docs) (Changes) 2009-04-22

Ruby OpenID Library

Version 1.1.4 (zip) (tar.bz2) (gem) (Docs) (Changes) 2007-08-30
Version 2.1.8 (zip) (tar.bz2) (gem) (Docs) (Changes)

Artigos Relacionados

0 comentarios:

Publicar un comentario