¿Cómo registramos de manera segura los usuarios en una aplicación?
Al crear aplicaciones web, es crucial garantizar la seguridad de las credenciales de los usuarios. Un error común es almacenar contraseñas en texto plano, lo que puede resultar en filtraciones masivas. Por lo tanto, un buen enfoque es delegar la autenticación a terceros o implementar un sistema seguro en nuestra aplicación.
¿Cómo delegar la autorización a terceros?
Empresas como Facebook y Twitter ofrecen servicios externos de autenticación que facilitan la implementación de un sistema seguro:
OAuth o servicios de terceros: Permiten a los desarrolladores utilizar servicios comunes de autenticación, evitando manejar contraseñas directamente.
Uso de tokens de acceso: Facilitan la sesión de usuarios y el rendimiento de acciones en su nombre.
¿Cómo implementar un sistema seguro de login y cifrado de contraseñas?
Puedes crear un fluido de autentificación y asegurar que las contraseñas no se almacenen en texto plano:
Registro del usuario: Gereamos una sesión con un nombre de usuario (username) y una contraseña (password).
Cifrado de contraseñas: Encriptamos las contraseñas antes de almacenarlas en la base de datos.
Verificación de usuarios utilizando consultas sencillas en la base de datos para verificar la existencia del usuario y la validez de la contraseña.
const data =await store.find({table:'users',query:{username: request.body.username}});if(data.password=== request.body.password){returngenerateToken(data);}else{thrownewError("Información inválida");}
¿Cómo generar un token de acceso?
Para crear un token de acceso se puede usar la librería jsonwebtoken para firmar los datos del usuario, proporcionando un método seguro de autenticación:
No guardar contraseñas en texto plano: Almacenar contraseñas cifradas usando técnicas como hashing.
Control de errores: Es esencial manejar los errores sin enviar mensajes detallados que puedan ayudar a un atacante (p. ej., "Información inválida" en lugar de detalles).
Validación regular de tokens: Implementar un proceso de verificación para asegurar que los tokens de acceso son válidos y no han sido comprometidos.
Implementando estos pasos, mejorarás significativamente la seguridad de las credenciales en tu aplicación web. Es momento de poner manos a la obra y reforzar las defensas de tu aplicación. Si tienes interés en profundizar en técnicas de seguridad y cifrado de contraseñas, sigue explorando y mantente actualizado. ¡Es el mejor camino hacia el conocimiento y la excelencia!
Muy buenas clases! Gracias!
Una recomendación que no hace al funcionamiento pero ayuda a orientarse mejor respecto al archivo con el que estamos trabajando en cada momento, o localizar más rápidamente los errores, etc:
A cada archivo network, controller u otros que se vayan agregando a la app, agregarle el nombre del componente al cual pertence.
Por ejemplo:
en el caso del componente user: user-network.js, user-controller.js
En el caso de auth: auth-network.js, auth-controller.js
Esto ayuda también a localizarlo más rápidamente en la función de búsqueda del editor que usemos.
!! Obviamente el index.js queda como index.js para que pueda cumplir la función que explica el profesor =) !!
Ademas, si es una clase la que exporta el archivo es recomendable poner el nombre en CamelCasing (notación de camello) De esa manera con el nombre de la clase puedes ver lo que exporta
En mi opinión no veo necesario nombrar los archivos de esa forma porque ya tienes el folder para identificar cada archivo.
hace 4 meses deje este curso en esta clase porque no entendia nada me frustre y lo deje, hoy estoy aqui de nuevo, agarre fuerzas, volvi a ver el curso de node basico que lo dicta Carlos y ahora voy por este video entendiéndolo a la perfección.! 👍🏻
Recomiendo este paquete module-alias para cambiar
required('../../../auth')
por
required('@auth')
Me gusta más usar Typescript y sus alias
Me gusta más programar de este modo tipo Error First (debe tener otro nombre) pero siento que es más limpio porque te quita un montón de indexados de bloques. Si alguna validación no cumple retornas o lanzas excepciones, si no, sigues el flujo en el mismo nivel de indexado.
¡Hola!
Primero se recibe la query en el parámetro llamado q (que es { username: username }), luego de esto se usa Object.keys(q) que nos retorna un array con el nombre de la propiedad de q (en este caso el nombre de la propiedad es "username") y lo guardamos en la variable keys.
Si hacemos un console.log(keys) tendríamos como output:
["username"]
Ahora, para acceder a ese valor, guardamos la referencia en la variable key usando keys[0].
Por último, al filtrar la columna se espera que el valor de item[key] (que sería el username de cada item) sea igual al valor (al username) de la consulta.
Espero esto te aclare un poco más. Recuerda que siempre puedes volver a repetir la clase para aclarar un poco más el tema.
Un saludo.
Lo que sucede es que keys crea un array de las llaves que contiene el objeto que le pasaste como parametro a la funcion. Por ende puedes navegar un objeto en bases a sus llaves y poder extraer cualquier informacion o modificar.
En este caso filtra en base a la condicion, si esta se cumple retorne lo que encuentra, sino retorna null.
Una duda, lo único es que al generar el token de acceso, le estamos pasando data del usuario y con ello la contraseña, eso no sería buena práctica no?
lo que pasa es que la contraseña debe ser cifrada antes de enviarse
La contraseña no debe de ir en el payload del JWT, aunque este cifrada es información sensible. Puedes revisar esta lectura de Auth0 que habla sobre los claims.
La contraseña debería ir en el token? una vez autenticado en el back, por que necesitaría enviar la contraseña en el token?
Supongo que no deberia ir en el payload del jwt, deberiamos removerla
noo! jamas! la contraseña solo se necesita a la hora del login para crear el token... en el token puedes poner el id y el username del usuario
Mucha repetición de nombres genéricos en carpetas y archivos. realmente confuso
Donde esta guardando la informacion del usuario para luego hacer el login? Supongo en cache? Porque el dummy.js siempre sigue igual... El ejercicio si me funciona solo no entendi esa parte
Hola, la data se guarda en el objeto db, como es una variable más, se almacena en la memoria principal (no en la caché) y si sufre cambios los cuales se conservan en memoria hasta que se reinicia la aplicación.
Puedes hacer un console.log(db) después de cada método en dummy.js para ver que está cambiando dependiendo de las peticiones que se realicen en la API.
Naturalmente en la memoria principal del servidor, cuando realizamos algún cambió en el server y estamos ejecutando con nodemon, este se reiniciara cada vez que le demos al CTR + S
Así que, por eso creamos el usuario cada vez que realizamos un cambió en el server :)
IMPORTANTE SABER ESTO SI NO USAS bodyParser:
app.use(express.urlencoded({extended:true}))//* Así ya no tenemos que instalar body-parserapp.use(express.json())//! Pero es importante usar esta línea también
Estuve muchas horas atorado por no saber que tenía que usar la segunda línea.
que clase de nivel...
✌
Excelente clase!
No se como ustedes ven el curso, pero yo lo veo un poco mal hecho, o es mi forma de ver las cosas o complica mucho las cosas con la clase dummy? , aparte que creo el modo de enseñar es un poco raro porque va haciendo las cosas de algún lado que creo va copiando porque algunas veces se equivoca en los nombres de las variables, aparte que los nombres de los archivos como network queda un poco extraño , tambien las variables en ingles y español me crean una confusion muy grande, soy le único que lo ve asi?..
por ejemplo tambien la variable col, ?? columna?
q de query?? o por que q?
quiza es la forma en como el aprendio o costumbre simplemente, por el ejemplo el archivo de response.js aunque me parece practico, en mi caso me limita, prefiero el manejo de respuestas y errores usando el archivo controller, y la logica y el llamado a la db, uso un archivo service.js, de esa manera separo la responsabilidad, y atomizo un poco mas el codigo, todo depende tambien de la arquitectura que quieras dar en el back
a mi me confundió demasiado y mejor aprendi desde otro lado, tuve que parar este curso.
alguien que me explique como funciona lo que hizo en la funcion query del minuto 3:40 me confundio con lo de let keys = Object.keys(q); aiudaaa XD
No me funciona upsert :/ siempre recibo name y usernmae como undefined y no sé a qué se deba.
Hola Santiago, en el condicional lo que evalúas es que si ++password++ o ++username++ tienen un valor diferente a null o vacío, pasan estos valores a través de la función upsert del controlador de auth para que a partir del id actualicen estas mismas propiedades en la tabla auth que tenemos en base de datos.
.
Espero haya sido claro si no, dímelo para explicarlo de mejor forma :)
Hola Andres, Si si , ya si me queda mucho mas claro, muchas gracias!