Anuncios

Bienvenidos sean a este post, hoy mejoraremos el tema de la encriptacion de passwords para nuestro servidor de usuarios.

Anuncios

En el post anterior ya le implementamos la posibilidad de ingresar como un usuario local o con nuestro usuario de twitter a la aplicacion notas pero en ningun momento segurizamos el tema de las contraseñas o passwords lo cual es una falla terrible, pero esto podemos solucionarlo con unas simples modificaciones en nuestro servidor de usuarios, para ello necesitaremos el codigo del post anterior, sino lo poseen les dejo un link para descargarlo:

Anuncios

Una vez descargado simplemente extraigan los dos directorios en el PC y con esto tendremos las dos aplicaciones funcionales, por el momento no trabajaremos con la aplicacion notas sino que nos centraremos en la otra, para ello vayan al directorio users, nuestro primer paso sera ejecutar el siguiente comando:

$ npm install bcrypt --save
Anuncios

Esto nos instalara el modulo encargado de la encriptacion, nuestro siguiente paso sera ir al archivo cli.mjs y al inicio agregaremos las siguientes lineas:

import { default as bcrypt } from 'bcrypt';
const saltRounds = 10;
Anuncios

El primero sera para importar el modulo llamado bcrypt, el segundo sera una constante que usaremos para indicar cuales seran los tiempos de CPU que usaremos para desencriptar la password, este tipo no sera el mejor metodo para hacerlo pero es uno de los mas estandarizados para estos temas, nuestro siguiente paso sera agregar la siguiente funcion:

async function hashClave(clave) {
let salt = await bcrypt.genSalt(salrRounds);
let hasheado = await bcrypt.hash(clave, salt);
return hasheado;
}
Anuncios
Anuncios

Esta funcion se encargara de crear el codigo hash de nuestra clave, para ello recibiremos el valor que correspondera a la contraseña, lo primero que haremos sera generar una variable que contendra el resultado de la funcion genSalt y el numero de la constante que definimos anteriormente, el valor que nos devuelve lo usaremos a continuacion, lo siguiente sera una variable donde almacenaremos el resultado de aplicar el metodo hash sobre la contraseña informada y el valor generado anteriormente, gracias a este ultimo no se generaran el mismo codigo hash cada vez que lo recarguemos, impidiendo que nos pueden atacar por fuerza bruta, por ultimo devolveremos ese codigo generado, nuestro siguiente paso sera modificar las tres acciones donde agregamos (add), modificamos (update) y la buscamos o creamos (find-or-create), primero modificaremos la siguiente linea:

.action((usuario, cmdObj) => {
Anuncios

La modificaremos de la siguiente manera:

.action(async (usuario, cmdObj) => {
Anuncios

Esto es para permitir que podamos usar la funcion asincronica,, esto debemos hacerlo en las tres acciones, lo siguiente sera modificar esta propiedad:

clave: cmdObj.password
Anuncios

La modificaremos de la siguiente manera:

clave: await hashClave(cmdObj.password)
Anuncios

Aqui en lugar de pasar el valor directo como haciamos antes le aplicamos la funcion que agregamos para pasar un codigo hash de la clave que le asignamos, recuerden que deben modificar la propiedad en las tres acciones que mencionamos anteriormente, ahora solo nos resta hacer una modificacion mas, para ello debemos ir al archivo user-server.mjs donde primero agregaremos la siguiente linea al comienzo:

import { default as bcrypt } from 'bcrypt';
Anuncios

Al igual que anteriormentte importaremos el modulo encargado para la encriptacion, luego buscaremos el bloque correspondiente a la verificacion de contraseña, /chequear, y en este tomaremos el siguiente bloque de codigo:

        try {
await conectarDB();
const usuario = await SQUser.findOne({
where: { usuario: req.params.usuario }});
let existe;
if (!usuario) {
existe = {
check: false,
usuario: req.params.username,
message: "Usuario no encontrado"
};
} else if (usuario.usuario === req.params.usuario
&& usuario.clave === req.params.clave) {
existe = { check: true,
usuario: usuario.usuario };
} else {
existe = { check: false,
usuario: req.params.usuario,
message: "Clave incorrecta"
};
}
res.contentType = 'json';
res.send(existe);
next(false);
} catch (err) {
res.send(500, err);
next(false);
}
Anuncios

Donde lo modificaremos de la siguiente manera:

        try {
await conectarDB();
const usuario = await SQUser.findOne({
where: { usuario: req.params.usuario }});
let existe;
if (!usuario) {
existe = {
check: false,
usuario: req.params.usuario,
message: "Usuario no encontrado"
};
} else {
let chkpwd = false;
if (usuario.usuario === req.params.usuario) {
chkpwd = await bcrypt.compare(req.params.clave,
usuario.clave);
}
if (chkpwd) {
existe = { check: true,
usuario: usuario.usuario };
} else {
existe = { check: false,
usuario: req.params.usuario,
message: "Clave o usuario incorrecto" };
}
}

res.contentType = 'json';
res.send(existe);
next(false);
} catch (err) {
res.send(500, err);
next(false);
}
Anuncios
Anuncios

Observen que resalte la parte que modificamos realmente, en este caso agregamos una nueva variable que usaremos para el chequeo de la contraseña y de manera predeterminada sera false, de vuelta verificamos que el usuario obtenido es igual al informado, en caso de ser verdadero procederemos a usar el metodo compare de bcrypt, esto es asi dado que no tenemos valores directos para compararlos sino que debemos verificar los codigos hash que obtengamos de la palabra informada y el valor almacenado en la base, en caso de coincidir le asignara un valor de true, despues tenemos un condicional donde verifica si esta nueva variable tiene el valor de true, en caso de ser verdadero asignaremos el valor de check como true y el usuario con el usuario, en caso contrario (ya sea porque no se encontro el usuario informado o bien las claves no coincidieron le asignara el valor de false a check, pasara el usuario que informamos y el mensaje de este posible error.

Anuncios

Despues el resto de la funcion sigue de la misma forma, el resto no es necesario modificarlo dado que los codigos hash son enviados desde el cliente y en este caso si debimos modificar el de chequeo por el metodo compare que debemos aplicar, con esto podemos hacer un par de pruebas, tomemos el caso de un usuario local que cree para la ocasion si lo buscamos directamente en la base se vera de la siguiente manera:

4|mirandma|clave|local|Miranda|Martin|[]|[]|2023-12-22 03:24:00.167 +00:00|2023-12-22 03:26:12.829 +00:00
Anuncios

Pueden ver que despues del usuario aparece su contraseña directamente, pasemos a actualizar y para ello usaremos el cliente, ejecutemos el siguiente comando:

$ node cli.mjs update --password clave mirandma
Anuncios

Esto nos permite «actualizar» la contraseña de nuestro usuario, en este caso volvemos a asignarle la misma, si volvemos a ingresar a la base y buscamos nuevamente al usuario nos devolvera los siguientes datos:

4|mirandma|$2b$10$8BpgSCzr9VSeu.t5lHSevuTwqVySQfWtkWezTi6mrhGHkJdZ/8BBq|local|Miranda|Martin|[]|[]|2023-12-22 03:24:00.167 +00:00|2023-12-24 02:12:06.642 +00:00
Anuncios

Ahora nuestra clave no se muestra mas sino que tenemos nuestro codigo hash generado, por lo tanto de ahora en mas agregaremos la contraseña encriptada, vamos a hacer una prueba mas para verificar como trabaja y para ello primero ejecutemos el siguiente comando:

$ node cli.mjs pwd-chk mirandma clave
Anuncios

En este caso le pasamos al chequeo de contraseña para verificar el nuevo funcionamiento, en mi caso me devolvio lo siguiente:

$ node cli.mjs pwd-chk mirandma clave
{ check: true, usuario: 'mirandma' }
$
Anuncios

Como pueden ver encripto la palabra que le informemos y comparandola con la almacenada en la base de datos, como coinciden nos devolvio el true para indicar el correcto funcionamiento probemos con otra contraseña:

$ node cli.mjs pwd-chk mirandma palabra
{
check: false,
usuario: 'mirandma',
message: 'Clave o usuario incorrecto'
}
$
Anuncios

Como pueden ver nos devolvio que la contraseña es incorrecta, con esto hemos terminado nuestra encriptacion de contraseñas para nuestros usuarios, a continuacion modificaremos la aplicacion notas para integrar estos cambios que realizamos.

Para ello debemos ir al directorio notas donde primero ejecutaremos el siguiente comando:

$ npm install bcrypt --save
Anuncios

Este nos instalara el modulo bcrypt que vimos anteriormente, nuestro siguiente paso sera ir al archivo users-admin.mjs en el directorio models y al comienzo agregaremos las siguientes lineas:

import { default as bcrypt } from 'bcrypt';
const saltRounds = 10;
Anuncios

Al igual que en el cliente primero importaremos el modulo de encriptacion y la constante que usaremos para determinar el tempo de CPU que usaremos para trabajar con las contraseñas, en el mismo archivo agregaremos la siguiente funcion:

async function hashClave(clave) {
let salt = await bcrypt.getSalt(saltRounds);
let hasheado = await bcrypt.hash(clave, salt);
return hasheado;
}
Anuncios

Esta es la misma funcion que vimos con el cliente y sera la encargada de devolvernos el codigo hash de la palabra que pasemos como clave/contraseña, nuestro siguiente paso sera modificar las siguientes funciones:

  • crear
  • cambiar
  • buscarCrear
Anuncios

En las dos primeras funciones buscaremos estas lineas:

.send({ usuario, clave, proveedor,
apellido, nombre, email, foto })
Anuncios

Y las modificaremos de la siguiente manera:

.send({ usuario, clave: await hashClave(clave), proveedor,
apellido, nombre, email, foto })
Anuncios

Al igual que en el caso del cliente si vamos a crear o modificar un usuario mediante este modelo debemos aplicar la funcion que agregamos anteriormente para generar el codigo hash en la base de datos, para el caso de buscarCrear al tenerlo de mejor forma que los dos anteriores simplemente buscaremos la propiedad clave en el mismo metodo send y lo modiifcaremos de la siguiente forma:

clave: await hashClave(perfil.clave),
Anuncios

Es exactamente lo mismo a lo anterior, en este caso no necesitamos modificar la encargada de chequeo de contraseñas dado que en realidad todo este proceso se realiza en el servidor y aqui simplemente lo invocamos, con esto ya tenemos todas las modificaciones realizadas, pueden probar de nuevo la aplicacion y notaran que siguen funcionando de la misma forma pero con los datos encriptados, antes de finalizar les dejo todos los archivos del proyecto asi como tambien los modificados en este post:

Anuncios

En resumen, hoy hemos visto como incorporar de una forma sencilla la posibilidad de encriptar las claves de los usuarios en el servidor, asi como tambien hemos hecho las modificaciones necesarias para poder chequear la contraseña almacenada con la informada, tambien hemos hecho las modificaciones necesarias en nuestro cliente para que pueda trabajar de la misma forma, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.50