"Es el peor de todos los planes"
Ciertamente lo es 😉
Introducción al proyecto del curso y su arquitectura
Arquitectura de un backend complejo
Estructuras de datos para nuestro proyecto
Creando la estructura principal
Estructura inicial del proyecto: API y rutas
Aislar el código de la base de datos
Rutas para usuarios
Documentación de nuestra API
Autenticación basada en tokens
JWT: Gestión de acceso
Autenticación: registro
Autenticación: login
Autenticación: cifrar contraseñas para evitar problemas de seguridad
Autenticación: gestión de permisos
Comprobar verificación con token
Gestión avanzada de errores: Throw
Almacenando datos: MySql
Base de datos real: MySQL
Completando la base de datos
Relacionando entidades: follow
Posts y likes
Microservicios en Node
Microservicios: pros y contras
Separando la base de datos a un microservicio
Conectando con nuestro microservicio de datos
Separando los posts a un microservicio
Gestión de microservicios con PM2
Puesta en producción serverless
Microservicios en Zeit Now, serverless y seguridad
Variables de entorno en Now y despliegue local
Cacheando nuestra aplicación
Caché como un microservicio. Redis
Conectando el microservicio a Redis
Conectar la API al caché
Puesta en producción en virtual machine
Desplegando los servicios de Node
Nginx como proxy inverso
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Carlos Hernández
Aportes 35
Preguntas 4
"Es el peor de todos los planes"
Ciertamente lo es 😉
el metodo login lo he hecho asi
async function login(username, password) {
const data = await store.query(TABLA, {
username
});
const equals = await bcrypt.compare(password, data.password);
if (!equals) {
throw new Error('information not valid');
}
return auth.sign(data);
}
No sé si yo me equivoqué en algo, pero en este punto el token se regresa con el password hasheado, algo que se supone que tampoco debería hacerse. Esto es debido a que en dummy, estamos devolviendo el objeto entero que encuentra en “auth”. Por lo que antes de generar el token, se debe eliminar al contraseña.
async function login(username, password) {
const data = await store.query(TABLE, { username })
if (await bcrypt.compare(password, data.password)) {
delete data.password
return auth.sign(data)
} else {
throw new Error('Invalid information')
}
}
Si alquien tiene inconvenientes al instalar bcrypt (como los tuve yo ) en windows, la solucion es instalar las windows build tools. Tienes 2 opciones, la primera por consola y la segunda descagando un instalador
npm install --global --production windows-build-tools
espero que les sea de ayuda
profe cuando nos subcribimos al jwt no deberia ser mejor quitar la password del payload?
Si tienen problemas para instalar bcrypt en ubuntu, lo que me funciono fue instalar primero node-gyp:
sudo apt-get install node-gyp
y después seguir con la instalación normal:
npm i bcrypt
Creo que simplemente implementado el await de Bcrypt.compare() en la validación es suficiente para obtener el mismo resultado
const login = async (username, password) => {
const data = await store.query(TABLA, { username })
if (await bcrypt.compare(password, data.password)) return auth.sign(data);
else throw new Error('Informacion Invalida');
}
NUNCA debemos guardar la contraseña como texto plano. Siempre deben estar encriptadas.
Debemos usar librerías de criptografía. Vamos a usar lo que usan los expertos en seguridad: npm i bcrypt
.
Ya que hablamos un poco sobre seguridad informática, creo que es un excelente momento para mencionar la ruta de Seguridad Informática
Si bien su enfoque me parece que es para ser un hacerk ético, creo que es importante conocer lo básico para crear programas que sean mucho más seguros.
npm i bcryptjs, por si en algún momento tienen problemas con bcrypt
si tienes problemas con el modulo bcrypt, traten de instalar bcryptjs
Gente yo lo hice así…
async function login(username, password) {
const data = await store.query(TABLA, { username: username });
const pass = await bcrypt.compare(password, data.password)
if (pass) {
// Generar token;
return auth.sign(data);
} else {
throw new Error('Informacion invalida');
}
}
Minuto 2:13 dice index.html jajaja
Es mas fácil comparar negado así, de ser falso se corta la ejecución y se levanta el error.
// Comparacion de contraseñas con bcrypt
if (!await bcrypt.compareSync(password, data.password)) {
throw new Error('Informacion invalida');
}
Excelente uso
En el controller de users veo que hay un error ya que creamos la data 2 veces:
async function upsert(body) {
const user = {
name: body.name,
username: body.username,
}
if (body.id) {
user.id = body.id;
} else {
user.id = nanoid();
}
if (body.password || body.username) {
await auth.upsert({
id: user.id,
username: user.username,
password: body.password,
})
}
return store.upsert(TABLA, user);
}
como podemos ver, despues de la condicional para valdiar que venga el password o el user que creamos la data el usuario vuelve a ser creado
mi solucion fuecolocar un excel y enviar un boom error badRequest:
async function upsert(body) {
const user = {
name: body.name,
username: body.username,
password: body.password,
};
if (body.id) {
user.id = body.id;
} else {
user.id = uuid.v4();
}
if (body.password && body.username) {
await auth.upsert({
id: user.id,
username: user.username,
password: user.password,
})
} else {
throw boom.badRequest('Username and password are required');
}
Lo resolví de está manera.
Para no usar promesas con bcrypt uso el postfijo Sync
y lo hace sincronamente.
Es muy importante cifrar todas las contraseñas para evitar leaks de seguridad.
A pesar de esto, tampoco es buena practica retornar la contraseña encriptada, ni guardarla en el token.
Para eso utilizamos el delete operator antes de retornar la información.
Por ejemplo:
delete myUser.password;
Si a pesar de utilizar esta linea de código, la contraseña aun esta siendo retornada, pueden re-convertir la propia variable a un objeto, para que el delete operator este disponible.
myUser = myUser.toObject();
delete myUser.password;
return myUser;
Comparto mi solución:
const login = async (username, password) => {
const data = await store.query(TABLE, { username: username });
const areEquals = await bcrypt.compare(password, data.password);
if (areEquals) {
// Generate Token
return auth.sign(data)
} else {
throw new Error('Invalid information');
}
}
✌
Es mala practica guardar la contraseña en texto plano por eso, se usan librerias como bcrypt para encriptarlas.
.
El segundo paramentro de bcrypt.hash indica cuantas veces ejecutara el algoritmo, en este caso ejecuta 5 veces el algoritmo, mientras mas veces se ejecute mas segura sera la contraseña, pero el proceso de generacion de la misma sera mas lento.
.
(lo recomendado son de 5 a 10 ejecuciones)
async function login(username, password) {
const data = await store.query(TABLA, {username: username});
const passwordIsOk = await bcrypt.compare(password, data.password);
if (passwordIsOk === true) {
return auth.sign(data);
} else {
throw new Error('Informacion invalida');
}
}```
wow clase magistral!!
Recuerden actualizar node para que bcrypt pueda trabajar
me gustaría mucho que explicara cómo es que toma la decisión de hacer las funciones asincronas y cuando no es necesario.
Nunca había visto la capa de seguridad como la dice carlos! y me gusta la idea! Gracias !!
Así me quedó la función login. Muy cortita y fácil de leer
const login = async (username, password) => {
const data = await store.queryUser( TABLE, { username } );
// cifrate data.password; then compare both passwords after login
return bcrypt.compare(password, data.password)
.then( equals => {
if( equals ) return auth.sign(data)
else return 'Invalid password';
});
}
Excelente se ve tan simple la logica, muy bien !!! 🤘🤘
Estupenda clase instructor Carlos, ahora me ha quedado más claro cómo podemos encriptar las contraseñas y compararlas con método compare que viene en este paquete para poder generar el Token.
Es increible lo sencillo que se puede manejar en NodeJS, algo tan complejo como la seguridad.
.
Ni hablar de la explicación del profesor, un fenómeno!
No es mala practica guardar datos sensibles como el Password en el token?. Se que esta cifrado, pero no debería hacerse no? 🤔
En vez de usar promesa utilize algo sincrono de bcryp 😃
async function login(username, password) {
const data = await store.query(TABLA, { username });
if (bcrypt.compareSync(password, data.password)) {
delete data.password;
return auth.sign(data);
} else {
throw new Error("Informacion Invalida")
}
}```
no puedo instalar bcrypt :’(
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?