Login y Control de Acceso en CodeIgniter 3 con Community Auth

24-10-2017 - Andrés Cruz

Login y Control de Acceso en CodeIgniter 3 con Community Auth

El Login también llamada autenticación es una función casi imprescindible en cualquier aplicación web, es una de los elementos fundamentales que tienen que estar cuando queremos llevar una simple página web a una aplicación web; y esto es decido que las aplicaciones web tienen siempre partes administrativas de la aplicación que se encuentran protegidas, con un... usuario y contraseña para autenticarse; en otras palabras un login que hoy veremos en CodeIgniter.

Otro elemento un poco menos necesario pero muy importante son el control de acceso o los permisos que le damos al usuario, generalmente se crear una implementación pobre en este aspecto, puros condicionales y cosas mal hechas, pero este paquete ofrece un completo control sobre nuestros usuarios, entre ellos están las famosas Listas de Control de Acceso o ACL.

En esta entrada se explica que es, como dar los primeros pasos con Community Auth y cuales son sus principales funcionalidades que en resumidas cuentas son: login, recuperación de cuenta o contraseña, Control de Acceso, Permisos a los usuarios, permisos bloqueo de usuarios y mucho más.

¿Qué es el Community Auth y en qué nos ofrece para el login y control de usuarios?

Community Auth es un paquete creado por un tercero, lo que quiere decir que no pertenece o no viene incluido al descargar el framework desde la web de CodeIgniter:Downloads si no lo tenemos que descargar desde otra web y posteriormente instalarlo; dicha instalación consta de varios pasos pero el resultado es tener una completa herramienta para el control de nuestros usuarios incluyendo la autenticación.

Community Auth funciona para CodeIgniter 3; y dentro de lo que componen su core permite la autenticación (login), manejo de roles, lista de control de acceso (ACL) para el manejo de los permisos, manejo de recuperación de contraseña, límite de logins fallidos entre otras características que podrás visualizar en el site.

Empezando con Community Auth: Qué podemos hacer

Su uso es muy sencillo, y el código que debemos incluir para emplearlo en nuestros controladores es realmente poco; tan solo el necesario para definir las funciones de acceso y sesión.

Pero este excelente paquete para CodeIgniter que podemos obtener de manera gratuita nos permite hacer mucho más, pero mucho más:

  • Podemos tener un completo sistema de permisos a nuestros usuarios, es decir, podemos limitar el acceso a cierto módulos, controladores y/o acciones en nuestra aplicación.
  • Podemos bloquear o bannear usuarios.
  • Podemos hacer el login, claro está.
  • Nos genera un token para recuperación de credenciales que luego podemos enviarsela al usuario mediante un envío de correos con CodeIgniter para que el usuario recupere sus credenciales
  • Protege nuestra contraseña con un hash para mayor seguridad.
  • Nos devuelve un objeto con los datos del usuario autenticado.
  • Factor para bloquear a usuarios por un tiempo determinado tras múltiples intentos fallidos
  • Login mediante Ajax o el tradicional.
  • Y mucho más; todo para tener un completo sistema de autenticación en CodeIgniter que lo puedes personalizar con CSS por ejemplo bootstrap.

Instalando Community Auth en nuestro proyecto en Community Auth

Su instalación no tiene mayor complejidad, simplemente nos descargamos la última versión de Community Auth disponible en su web: Download Community Auth y seguimos los pasos para su instalación los cuales son unos 16 que puedes encontrar en el siguiente enlace: Instrucciones de instalación de Community Auth.

En resumidas cuentas su instalación consiste en...

Descargar, descomprimir y copiar la carpeta community_auth dentro de la carpeta third_party, debemos copiar los php ubicados en la carpeta core dentro del la carpeta core de nuestro proyecto, crear la ruta al login de nuestra aplicación en el archivo de routes, habilitar el uso de los hooks y por supuesto, ejecutar el SQL en la base de datos de nuestro proyecto para copiar el esquema del paquete.

Funcionalidades principales de Community Auth

Community Auth cuenta con una buena cantidad de funcionalidades a las cuales les podemos sacar provecho para el tipo de funcionalidades que ofrece según sea necesario; estas funcionalidades las podemos configurar mediante el archivo de configuración de este paquete ubicado en:

Localización: /application/third_party/community_auth/config/authentication.php

Configuraciones principales

Community Auth cuenta con una gran cantidad de funcionalidades que resultan útiles en la mayoría de los casos; para evitar que hackeen la página mediante fuerza bruta (que intenten probar múltiples combinaciones de contraseñas de manera sucesiva) se puede emplear la configuración de max_allowed_attempts que por defecto se encuentra de la siguiente manera:

$config['max_allowed_attempts'] = 5;

Lo que significa que si un usuario realiza 5 intentos de inicio de sesión de manera incorrecta, la aplicación no le permitirá probar otra combinación de usuario contraseña por un tiempo determinado que puedes configurar mediante la siguiente configuración expresada en segundos:

$config['seconds_on_hold'] = 600;

Los bloqueos se realizan a nivel de IP asi que si estamos en Localhost posiblemente la URL bloqueada sea la de localhost: 127.0.0.1, pero si estamos en la web, sería la que nos da nuestro proveedor de interés; en ambos casos puedes consultar la tabla ips_on_hold para ver el resultado en caso de que se te bloquee el acceso en alguna ocasión:

Bloqueo de IPS

Al eliminar manualmente el registro el bloqueo acaba.

También puedes denegar el acceso a un usuario (un código 403 de HTTP) cuando este no tiene éxito al momento de ingresar:

$config['deny_access_at'] = 10;

Que por defecto se encuentra en 10 cuyo valor representa el número de intentos fallidos por parte del usuario para denegar el acceso.

Puede evitar múltiples logins o autenticaciones concurrentes mediante la configuración:

$config['disallow_multiple_logins'] = FALSE;

Manejo de niveles y roles

Como se indicó en un inicio, Community Auth permite el manejo de permisos y roles que fácilmente son asignados a un usuario creado en nuestra base de datos en el campo auth_level de la tabla users:

Usuarios de la aplicación

De tal forma que cada uno de nuestros usuarios en base de datos debe pertenecer a un nivel previamente configurado mediante levels_and_roles de nuestro archivo de configuración:

$config['levels_and_roles'] = array(
    '1' => 'customer',
    '6' => 'manager',
    '9' => 'admin'
);

Y claro que podemos personalizar esta configuración que no es más que un array en PHP de la manera que queramos, en donde mientras más alto sea el valor del nivel, más alto será el nivel de acceso.

Un usuario con nivel de acceso 9 puede acceder al contenido de un usuario con nivel de acceso 6 pero este usuario con nivel de acceso 6 no puede acceder a uno con nivel de acceso 7 o superior.

Desde nuestro controlador, y dentro de nuestro mismo __construct() podemos ingresar la siguiente línea de código para empezar a trabajar con los niveles y accesos a nuestro sistema.

$this->require_min_level(MY_LEVEL);

En dónde "MY_LEVEL" es el nivel de bloqueo, que varía según las los niveles de acceso creados anteriormente.

Podemos colocar la línea anterior en el __construct() para que cada una de nuestras acciones herede dicho nivel de acceso (el método __construct() se invoca antes que nuestras acciones) o podemos colocarlo en cada una de las acciones que nosotros queramos.

Puedes obtener más información en la documentación oficial:

Community Auth authentication.php

Dando los primeros pasos con Community Auth

Ya conocidas las configuraciones y funcionalidades principales del paquete Community Auth, ahora veamos qué otras características podemos usar.

Para tener un fácil acceso, manejaremos todo lo que tenga que ver con nivel de acceso en un controlador llamado User desde aquí manejaremos el login, logout, y recuperación de la cuenta; el login luce de la siguiente manera:

public function login() {

	if ($this->uri->uri_string() == 'user/login')
		show_404();

	if ($this->session->userdata("auth_level") != NULL) {
		redirect("/user/logout");
	}

	if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
		$this->require_min_level(1);
	}

	$this->setup_login_form();

	$html = $this->load->view('user/page_header', '', TRUE);
	$html .= $this->load->view('user/login_form', '', TRUE);
	$html .= $this->load->view('user/page_footer', '', TRUE);

	echo $html;
}

El logout llamamos al método correspondiente y destruimos la sesión:

   $this->authentication->logout();

$redirect_protocol = USE_SSL ? 'https' : NULL;
$this->session->sess_destroy();
redirect(site_url(LOGIN_PAGE . '?logout=1', $redirect_protocol));

Y por último la funcionalidad que nos permite recuperar la contraseña, la cual consiste en crear un token para el usuario que solicite dicha recuperación que debería ser enviada mediante un correo electrónico.

 public function recover() {
        // Load resources
        $this->load->model('examples_model');
        $this->load->library('emails');

        /// If IP or posted email is on hold, display message
        if ($on_hold = $this->authentication->current_hold_status(TRUE)) {
            $view_data['disabled'] = 1;
        } else {
            // If the form post looks good
            if ($this->input->post('email')) {
                if ($user_data = $this->examples_model->get_recovery_data($this->input->post('email'))) {
                    // Check if user is banned
                    if ($user_data->banned == '1') {
                        // Log an error if banned
                        $this->authentication->log_error($user_data->email);

                        // Show special message for banned user
                        $view_data['banned'] = 1;
                    } else {
                        /**
                         * Use the authentication libraries salt generator for a random string
                         * that will be hashed and stored as the password recovery key.
                         * Method is called 4 times for a 88 character string, and then
                         * trimmed to 72 characters
                         */
                        $recovery_code = substr($this->authentication->random_salt()
                                . $this->authentication->random_salt()
                                . $this->authentication->random_salt()
                                . $this->authentication->random_salt(), 0, 72);

                        // Update user record with recovery code and time
                        $this->examples_model->update_user_raw_data(
                                $user_data->user_id, [
                            'passwd_recovery_code' => $this->authentication->hash_passwd($recovery_code),
                            'passwd_recovery_date' => date('Y-m-d H:i:s')
                                ]
                        );

                        // Set the link protocol
                        $link_protocol = USE_SSL ? 'https' : NULL;

                        // Set URI of link
                        $link_uri = 'user/recovery_verification/' . $user_data->user_id . '/' . $recovery_code;
                        $this->emails->recuperar_cuenta($link_uri, $user_data->email);

                        $view_data['special_link'] = anchor(
                                site_url($link_uri, $link_protocol), site_url($link_uri, $link_protocol), 'target ="_blank"'
                        );

                        $view_data['confirmation'] = 1;
                    }
                }

                // There was no match, log an error, and display a message
                else {
                    // Log the error
                    $this->authentication->log_error($this->input->post('email', TRUE));

                    $view_data['no_match'] = 1;
                }
            }
        }

        echo $this->load->view('user/page_header', '', TRUE);
        echo $this->load->view('user/recover_form', ( isset($view_data) ) ? $view_data : '', TRUE);
        echo $this->load->view('user/page_footer', '', TRUE);
    }

A modo de ejemplo se coloca una función para enviar dicho enlace o link para recuperar la cuenta mediante un helper $this->emails->recuperar_cuenta($link_uri, $user_data->email);.

Seguramente querrás cambiar el estilo de cada una de las páginas que maneja Community Auth para el login, recuperación de cuenta, etc; las puedes encontrar en la siguiente carpeta:

/application/third_party/community_auth/views/user/*

En general el código es de fácil compresión y ya viene listo al momento de descargar el paquete, tan solo debemos usarlo y terminar de configurar cualquier parámetro dentro de los mismos según sea necesario.

Para pintar los datos de sesión, una vez autenticado desde nuestro controlador que hereda de la clase MY_Controller que nos la ofrece este paquete de autenticación para hacer nuestro login y que se ubica en la carpeta core de nuestra aplicación, podemos hacer lo siguiente para cargar los datos en sesión y de esta manera emplearlos en cualquier parte de nuestra aplicación:

$this->session->set_userdata(array(
	'email' => $this->auth_data->email,
	'name' => $this->auth_data->username,
	'id' => $this->auth_data->user_id,
	'auth_level' => $this->auth_data->auth_level
));

Conclusiones

En esta entrada vimos cómo manejar este completo sistema para la autenticación que incluso podemos emplearla mediante ajax; podemos personalizar la parte visual como lo queramos; por ejemplo, bootstrap, que en definitiva nos ofrece un importante ahorro de trabajo ya que funciona perfecto con CodeIgniter.

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.