Etiqueta: Autenticación

  • Cómo autenticar usuarios en una aplicación web con PHP

    Cómo autenticar usuarios en una aplicación web con PHP

    Este es un tema que suele causar bastante confusión en la gente que se enfrenta con este problema por primera vez… hay tantos usuarios/passwords/niveles de autenticación que si no se presta mucha atención es fácil perderse.

    Lo principal es entender que la autenticación es un proceso de comunicación entre dos entidades:

    1. Un cliente
    2. Un servidor

    El cliente es el que se identifica (generalmente utilizando un par «nombre de usuario» + «contraseña») y el servidor es quien valida esas credenciales y devuelve algún tipo de identificador de acceso.

    Podríamos pensarlo como el guardián de una discoteca en una fiesta privada. Cualquiera puede pararse ante el grandote y decirle que es uno de los invitados, pero si tu nombre no figura en la lista… por más que patalees, te vas a quedar afuera (Y aún si tu nombre figura, si te olvidaste el DNI… más vale pegar la vuelta).

    En el caso de una aplicación web, existen muchos clientes y servidores interviniendo (De hecho, como vas a ver en breve, varios de estos servidores son a la vez clientes… ¡como para no confundirse!).

    En el clásico esquema de un request:

    El primer cliente que aparece es el browser (FireFox, Chrome, IE, etc…) y el servidor (En este post me voy a referir a «cliente» y «servidor» en su sentido como procesos, no como computadoras) es el webserver (Apache, NginX, etc…).

    Entonces, el primer nivel de autenticación que debe superarse es este: el cliente que se conectó al webserver ¿presentó credenciales válidas?

    Hoy en día es extremadamente raro encontrarse con este tipo de autenticación (por lo general, los servidores web están configurados de modo de aceptar conexiones de cualquier cliente sin pedir demasiado, pero se puede configurar este tipo de autenticación).

    Una vez que el webserver dió la bandera verde, dependiendo de cuál haya sido el pedido del cliente, se le enviará una respuesta (generalmente un texto HTML).

    El siguiente nivel de autenticación es el del webserver contra el servidor de base de datos:

    Desde el punto de vista del servidor de base de datos, quien hace la conexión es el cliente (Es indiferente si se trata de una acción iniciada por un humano o por una computadora… en última instancia, la comunicación siempre es computadora-a-computadora…).

    Entonces acá tenemos:

    1. Un cliente del webserver (el navegador)
    2. Un cliente del servidor de bases de datos (el webserver)

    Al igual que en el ejemplo anterior, el cliente (en este caso el webserver), debe proveer de credenciales para que el servidor de bases de datos le permita acceder a sus servicios.

    Es importante notar que las credenciales que utiliza el navegador para autenticarse ante el servidor web no tienen por qué ser las mismas que usa el webserver para conectarse a la base de datos (De hecho, lo más probable es que sean completamente diferentes).

    Hasta ahora te mostré los niveles más bajos de autenticación (Los que podríamos llamar de infraestructura), pero existe un tercer nivel de autenticación: el de la aplicación.

    En este nivel es responsabilidad del propio sistema (es decir tuya :)) decidir quién puede ingresar y qué puede hacer una vez adentro.

    Pueden usarse diversos mecanismos para lograr este tipo de autenticación: el más simple (y común) es el almacenamiento de nombres de usuario y contraseñas en una base de datos a la que la aplicación tiene acceso. Otro método más elaborado es el uso de servicios de terceros (Google, Facebook, Twitter, etc…).

    Entonces, recapitulando…

    Cuando te enfrentás a algo como esto:

    Lo que estás viendo es el resultado de la interpretación de HTML por parte de tu navegador.

    Los datos que ingreses ahí van a ser recibidos primero por algún webserver y luego, a través de algún script (PHP por ejemplo), contrastados contra alguna base de datos (A la cual el script accederá utilizando sus propias credenciales).

    Es por eso que, por lo general, una aplicación php tenga su propio username definido en su servidor de base de datos, aunque tenga un gran número de usuarios propios (visitantes registrados).

    ¿Te quedó alguna duda? ¡Espero tus comentarios!

  • Cómo autenticar usuarios con redes sociales en PHP

    Cómo autenticar usuarios con redes sociales en PHP

    Algo que se ha puesto bastante de moda últimamente es la posibilidad de logearse en un sitio cualquiera usando un usuario creado para otro (Por ejemplo, logearte a StackOverflow usando tu Gmail o a Clarin usando tu Facebook).

    Este enfoque presenta varias ventajas:

    1. Para el usuario significa no tener que inventar (¡y recordar!) una contraseña más y, por si eso fuera poco, ingresar a tu sitio haciendo un solo click.
    2. Para el sitio significa no tener que almacenar información de usuarios ni hacer un doble-opt-in (Se asume que el proveedor de autenticación ya ha validado la identidad del usuario).

    Ahora bien, desde el punto de vista de tu aplicación… ¿cómo podés implementar esto?

    La mayoría de los grandes proveedores de autenticación (Gmail, Facebook, Twitter, etc…) utilizan un protocolo que se conoce como OAuth, muy seguro pero algo complejo de implementar a mano.

    Afortunadamente existen algunas librerías que hacen el trabajo sucio por nosotros. Veamos algunas:

    HybridAuth

    Esta librería (Puede consultarse la documentación acá) ofrece muchas posibilidades además del login (Compartir en redes sociales, acceso a perfiles, etc…).

    Como de costumbre, el uso recomendado es mediante Composercomposer init y después (si no incluiste la dependencia interactivamente) composer require hybridauth/hybridauth

    En definitiva, el archivo composer.json debería quedar similar a:

    {
     "name": "leeway/hybrid_auth",
     "description": "Test de hybrid_auth",
     "require": {
     "hybridauth/hybridauth": "^2.10"
     },
     "authors": [
     {
     "name": "Mauro Chojrin",
     "email": "mauro.chojrin@leewayweb.com"
     }
     ]
    }

    Luego, instalamos las dependencias usando composer install y estamos listos para comenzar nuestra aplicación.

    HybridAuth provee una clase principal: Hybrid_Auth.

    Lo primero que vamos a necesitar hacer es, obviamente, crear una instancia de esta clase. El parámetro que recibe el constructor es la configuración.

    Esta configuración tiene una cantidad de parámetros, algunos opcionales y otros obligatorios. Los básicos son:

    • base_url URL a donde el proveedor (Google, Facebook, Twitter, etc…) redireccionará una vez realizada la autenticación. A esta URL se la conoce como callback
    • providers Lista de proveedores que quieras usar (¡Claro que deben estar soportados por la librería!).
      • enabled true o false
      • keys Credenciales de acceso para tu aplicación:
        • id Identificación de tu aplicación
        • key Clave de acceso
        • secret Clave secreta

    Las credenciales de acceso las debes generar en cada proveedor (Puedes ver cómo hacerlo para Facebook siguiendo este enlace, para Google este y para Twitter este).

    Veamos un ejemplo:

    <?php
    
    return [
            'base_url' => 'http://localhost:8080/vendor/hybridauth/hybridauth/hybridauth/',
            'providers' => [
                            'Facebook' => [
                                    'enabled' => true,
                                    'keys' => [
                                            'id' => 'XXXX',
                                            'secret' => 'YYYY',
                                    ]
                            ]
                    ],
    ];

    Aquí lo importante es (más allá de la identificación de mi app en particular), la dirección a la que Facebook (o el proveedor de autenticación) deberá realizar su callback.

    En mi caso es una dirección que comienza con http://localhost:8080 porque estoy desarrollando una prueba de concepto usando el servidor embebido en PHP, si fuera un sitio productivo habría que escribir el dominio.

    Sin entrar en los detalles de OAuth (U OpenID que a los efectos de este artículo no distan mucho), el circuito de autenticación implica dejar por un momento nuestro sitio para pedirle al usuario que realice un login en otro y, una vez logrado esto, vuelva.

    Toda esta complejidad precisamente la maneja HybridAuth a través del archivo vendor/hybridauth/hybridauth/hybridauth/index.php cuyo contenido no es más que:

    <?php
    /**
    * HybridAuth
    * http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
    * (c) 2009-2015, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
    */
    
    // ------------------------------------------------------------------------
    //      HybridAuth End Point
    // ------------------------------------------------------------------------
    
    require_once( "Hybrid/Auth.php" );
    require_once( "Hybrid/Endpoint.php" );
    
    Hybrid_Endpoint::process();

    Obviamente toda la magia está en el método Hybrid_Endpoint::process() el cual, una vez validada la autenticación, volverá a redirigir al visitante hacia la página en la que ésta se solicitó.

    En mi ejemplo sería el archivo login.php:

    <?php
    
    require_once __DIR__.'/vendor/autoload.php';
    
    session_start();
    $config = require_once 'config.php';
    
    $ha = new Hybrid_Auth( $config );
    
    try {
            $facebook = $ha->authenticate( 'facebook' );
            $user_profile = $facebook->getUserProfile();
    
            echo 'UserProfile: '.print_r($user_profile, 1);
    } catch ( Exception $e ) {
            echo $e->getMessage();
    }
    

    Al cual se accede desde login.html:

    <html>
            <form>
                    <fieldset>
                            <legend>Identif&iacute;cate con tu Facebook</legend>
                                <a href="login.php">Autorizar</a>
                    </fieldset>
            </form>
    </html>
    

    ¿Quedó alguna duda? ¡Espero tus comentarios!

  • Cómo autenticar usuarios vía HTTP usando PHP

    Cómo autenticar usuarios vía HTTP usando PHP

    La autenticación a nivel de HTTP se activa mediante la configuración del webserver.

    Es el nivel más bajo de autenticación que puede tenerse en un entorno web, ya que lo que va a verificar es que el cliente que solicita un determinado recurso (URI) tenga acceso a él, antes de hacer ningún otro tipo de verificación.

    De lo que estoy hablando es de lo que sucede cuando querés ingresar a un sitio, por ejemplo http://localhost y, en lugar de ver el contenido del sitio, se abre una ventana como esta:

    Por lo general, no es mucho lo que puede validarse (No hay posibilidad de ofrecer diferentes niveles de acceso ni nada parecido), con lo cual, no es algo que suela utilizarse en entornos de acceso público.

    La forma de configurar este tipo de acceso depende del web server que uses.

    En el caso de Apache, la forma de lograrlo es:

    1. Crear un archivo de autenticaciones (Usando la utilidad htpasswd por ejemplo).
    2. Dentro de la configuración del servidor, definir un bloque para el DocumentRoot:
     <Directory "/var/www/html">
       AuthType Basic
       AuthName "Restricted Content"
       AuthUserFile /etc/apache2/.htpasswd
       Require valid-user
     </Directory>
    1. Reiniciar el servidor (O, menos drástico, recargar la configuración).

    A partir de este momento, cualquier usuario que desee ingresar a tu sitio tendrá que identificarse (Ante el webserver).

    Otra forma de usar este tipo de autenticación (que no depende de la configuración del webserver), es hacerlo a través de PHP:

    La clave aquí es el uso de la función header (y conocer algunos detallitos del protocolo HTTP :)).

    Básicamente se trata de un script que será invocado dos veces:

    La primera será la que solicite las credenciales y la segunda será la que valide (Lo mismo que podrías hacer si hicieras un login clásico, con la diferencia de que la segunda llamada se produce automáticamente al completar los datos).

    El código es este:

    <?php
    if (!isset($_SERVER['PHP_AUTH_USER'])) {
        header('WWW-Authenticate: Basic realm="My Realm"');
        header('HTTP/1.0 401 Unauthorized');
        echo 'Este texto se ve si el usuario cancela';    
    } else {
        echo "<p>Hola {$_SERVER['PHP_AUTH_USER']}.</p>";
        echo "<p>Tu password es {$_SERVER['PHP_AUTH_PW']}.</p>";
    }

    El if está para validar si estás en la primera llamada o en la segunda. Las claves de la variable de $_SERVER se completan automáticamente con lo ingresado por el usuario.

    Esta forma puede ser más conveniente ya que te permite independizarte del WebServer con el que estás trabajando (Y por lo tanto, cambiarlo será más sencillo).

    Por último, una forma de acceder al sitio sin pasar por el formulario es pasar las credenciales como parte de URL:

    http://user:password@localhost

    ¿Qué forma de autenticación usas en tus aplicaciones?