[MÚSICA] [MÚSICA] Hola, vamos a comenzar a crear nuestro entorno de seguridad, nuestro modelo de seguridad, incorporando password y algunas validaciones por token que utilizaremos vÃa mail para certificar que el usuario haya ingresado el email que es suyo y de esa forma, demos una autenticación del estilo de dos factores, como vimos en nota teórica y para eso vamos a usar algunos servicios de mail y comenzaremos por trabajar, extendiendo lo que es nuestro modelo de usuario, agregándole email, password y algunos valores más, relacionados con la verificación de la cuenta y los token de seguridad. Para eso, lo primero que vamos a hacer es, acá vamos a hacer un pequeño cambio. Aprovechamos la flexibilidad de los esquemas de Mongo y acá lo que podemos hacer es, definirle que esto va a ser String, como estaba antes. Vamos a ponerle trim true. Esto significa que cuando se cree nombre, si hay espacios vacÃos al principio y al final, se van a sacar y después le vamos a decir que esto se va a requerir. Sabe que el nombre para nosotros, al menos en este momento es obligatorio. Y luego le ponemos un mensaje en el caso de que ocurra un error, que es lo que queremos mostrar. En este caso, pareciera ser obvio que, si le estamos diciendo que se requiere nombre, el mensaje deberÃa ser que el nombre es obligatorio. Lo que sucede es que estas herramientas generalmente, como están todas en inglés, traen por default la descripción del error o de la violación de la validación, en inglés. Asà que lo vamos a tener que re-escribir las veces que lo necesitemos. Lo segundo que vamos a hacer es agregarle el email, vamos a decirle que es de tipo String. Ahora vamos a hacer lo mismo, trim true, asà nos ahorramos cualquier tipo de problema en ese sentido. Vamos a decirle que esto, obviamente va a ser requerido. Le pondremos que es true y que el email es obligatorio. Vamos a aprovechar otra función que tenemos disponible, que es lowercase. Esto es que en el momento de guardar, ponga todo en minúscula, todo en minúscula como corresponde para los mails. Luego vamos a agregarle, una validación y aquà you vamos a requerir una nueva función, que es que, cómo esto es un String, el email podrÃa estar mal armado obviamente, ¿no? Entonces lo que vamos a hacer es utilizar una, vamos a definir una función y vas a ver cómo fácilmente la podemos agregar a nuestro modelo. La voy a escribir acá arriba del esquema, la estoy copiando y pegando. Esto, como verás es una función estándar. Lo que definimos acá es, una constante, una variable de nombre re, que es un objeto Regex. Todos estos sÃmbolos que parecen raros, es un Regex. Regex se escribe asÃ, Regex. Esto de las expresiones regulares, que eso significa Regex, regular expressions, tienen un método que es test, que validan que el String que le pasemos, digamos el re aplique, se encuentre en el String que le pasamos. Entonces, de esta manera este Regex que parece un poco raro, lo que hace es básicamente validar que si el testeo nos da vedadero, este String es un email válido, si no, el email no, no está bien formado. Esto lo puedes copiar y pegar, lo puedes escribir o puedes googlear Regex para validar un email y basar que hay un montón de expresiones regulares todas muy similares que validan, validan mails. Bien, entonces lo que aprovechamos acá es esta función que es validate, que le pasamos que función es la que queremos ejecutar sobre este campo al momento de guardar, y luego en el caso de que no sea válido, le ponemos un mensaje de error, por favor ingrese un email válido. Por último, para asegurarnos si esto es una validación, que le ponemos, acá le vamos a poner directamente, un criterio de validación a nivel dato en el momento de guardar que es el match, ¿no? Es decir, todo lo que me esté ingresando tiene que matchear con esto. ¿Cuál es la diferencia con el validate? Bueno, aquà les podemos tipificar el mensaje error que necesitábamos, este se ejecuta en el momento de guardado, forma parte de Mongoose. El match you es algo que va a correr a nivel Mongo más que nada y con los dos es suficiente para cubrirnos de cualquier tipo de diferencia o error. Siguiente campo que vamos a agregar es password que va a ser de tipo String. Lo mismo, un trim true. Que esto, vamos a dejárselo porque puede haber password que quieran agregarle espacios vacÃos al final. No es habitual, no es habitual, pero bueno, si la persona quiere dejar, password es obligatorio. Ver el mensaje, ¿no? Obligatorio. Perfecto. Bueno, por último vamos a agregar dos campitos más, que nos va a servir para esto de los token, ¿no? Password resetTokenString y passwordresetToken expires. ¿Por qué usamos palabras e inglés para ésto? Bueno, podemos poner en español sÃ, por supuesto pero esta expresión expires, la vas a ver cuando enseguida hagamos la configuración de las cookies y demás, ¿no? La expiración del token, ¿no? Entonces hay algunos términos que es bueno que te vayas familiarizando con el inglés, estos términos que son técnicos, porque asà es cómo los vas a ver en todas las documentaciones, ¿no? La expiración del Token, el Token expiration y está bueno que nuestro modelo, respete el mismo, si vamos a usar el programa en español, no hay ningún problema pero en algunos cuestiones técnicas, está bueno que nuestro modelo se corresponda con la realidad de la herramienta. Pensalo de esta manera, quizás, cuando alguien vea nuestro modelo y haya trabajado con varias [INAUDIBLE] de seguridad, está bueno que se sienta cómodo y familiarizado con la terminologÃa que utilicemos. De esa forma achicamos la brecha de comprender el modelo y a su vez comprender qué significa lo que quisimos hacer, ¿no? Que cualquiera ve password y entiende enseguida que esto se trata de un password y la expiración del Token, lo mismo, ¿no? Y por último, vamos a agregarle el verificado, que este va a ser, el tipo va a ser Boolean, porque vamos a ponerlo como verdadero falso, y el default va a ser, false, ¿no? Esto, acá lo que le vamos a decir utilizando Mongoose, es que el valor por defecto si no lo especificamos, sea false. Y en la base de Mongo nos va a aparecer false, si no especificamos el verificado. you casi estamos con nuestro, nuestro modelo, nuestro modelo de usuario. Repasando rápidamente, hicimos que el nombre que tenga un [INAUDIBLE] un nombre, un email, un password. you le preparamos los valores, estos dos, para el Token y vamos a definirle si es verificado o no. El Token, que es esa clave larga, lo vamos a usar para, le vamos a mandar un email, en el momento en que se registra en nuestro sitio, la persona y en ese email va a tener un Token que unifica, va a estar asociado a esta cuenta. Ahora enseguida vamos a crearla. Entonces cuando el usuario ingrese a su email, al que haya ingresado aquÃ, va a poder verificar la cuenta y este valor se va a pasar, vamos a tener que hacer que se pase a true. De esa forma, fijate lo que estamos logrando, que la persona cuando ingrese al sitio, va a ingresar su email y password. Pero este usuario si you está verificado, quiere decir que el email que ingresó es correcto y que se tuvo que autenticar en su cuenta de mail. Por ejemplo en Gmail o en Yahoo o en cualquier otro proveedor de mail, que, que utilice. De esta forma, estamos teniendo you, si esto no es autenticación en dos pasos, pero sà lo podemos tomar como una verificación más segura. Es decir, los usuarios que digan cuando se registren, you sabemos que si están utilizando esa cuenta de email, probablemente sean quién dicen ser y sea un usuario real, ¿no? Por supuesto, pueden crear un email trucho y activar la cuenta con ese email trucho. Por supuesto eso puede pasar y no estamos exentos, pero suponiendo que la mayorÃa de los casos van a ser reales y son los que nos interesan, o sea estamos tranquilos de que una vez que esté verificado todo el canal de comunicación que usemos vÃa email con nuestro usuario, esa cuenta existe, está bien ingresada y es válida. Eso nos va a dar bastante tranquilidad, al momento de notificarle cosas de nuestra aplicación. ¿Qué vamos a hacer ahora? Vamos a agregar un método más antes de agregar el token y ir preparando nuestro control de nuestras rutas. Vamos a agregar usuario esquema. Vamos a hacer un pre, ¿qué significa esto? Esta función pre lo que va a hacer es, permitirme cerrarlo acá, lo que vamos a hacer acá, lo que estamos indicando es que antes del save pre save, o sea el evento que le pongamos aquÃ, [INAUDIBLE] de persistencia porque ha estado trabajando con el evento de Mongo, quiero que ejecutes esta función y lo que vamos a escribir ahora. Entonces cada vez que se hace un save se va a ejecutar esta función, antes de hacer el save, ¿está bien? Entonces cuando le hacemos a un objeto .save inmediatamente se ejecuta esta función y luego continua con lo que vaya a hacer el evento save. Entonces esto es un lugar bueno para hacer esto que vamos a hacer ahora que es lo siguiente. Primero vamos a preguntar, lo que vamos a hacer acá básicamente el password asà como está que es plano es bastante inseguro. ¿Por qué? Porque si alguien puede tener acceso a nuestra base de datos lo que puede hacer justamente es observar los passwords, las claves, y robarse las cuentas. Entonces lo que se suele hacer una práctica habitual es encriptar los passwords, encriptarlos y cada vez que se actualice ese password lo tenemos que encriptar nuevamente, ¿no? Y por otro lado al momento de comparar password tendremos que usar una función que es la que se encargue esta de encriptar que sabe cómo generar esas claves crÃpticas por asà decirlo, para poder ver si los passwords son correctos. Bien, entonces hacemos el isModified password. Entonces si el password cambió porque sino no hace falta que lo hagamos, vamos a hacer this.password bcrypt, que este es un módulo de encriptación, ahora vamos a revisar si lo tenemos incorporado. HashSync.thispassword,saltRounds, que seguro no tenemos definido. Bien, y a lo último hacemos un next para que continue el save como corresponde. Bien bcrypt, no lo tenemos definido, vamos a definirlo. Y el salt lo mismo. Ahora enseguida yo te repaso brevemente qué es esto. Entonces primero vamos a definir el salt, saltRounds igual 10 y vamos a usar el bcrypt require bcrypt. Vamos a revisar si lo tenemos en nuestro package.json. No. Vamos a instalarlo npm install bcrypt. [INAUDIBLE] save. Este es un módulo que nos va a permitir encriptar strings básicamente, no tiene mucho más ciencia que eso. El salt lo que le va a hacer es introducirle cierta aleatoriedad a esa encriptación, es decir. ¿Por qué? Porque una misma encriptación si yo pongo por ejemplo la palabra clave segura, es un string, si yo encripto y algoritmo ese mismo siempre, cualquier usuario que use la misma clave va a tener el mismo password. Pero sin embargo, nos interesa eso distinguirlo para darle un nivel de seguridad un poco mayor. Ahà es donde interviene el salt, que es lo que se va a guardar dentro de esta encriptación. Y eso si en el string va a ser el mismo, este valor de salt por asà decirlo, es la que va a darle una aleatoriedad mayor a la, mejor dicho va a introducirle aleatoriedad a la encriptación. No te preocupes ahora. Esto es un tema de algoritmos de seguridad. Nosotros usamos el módulo, usamos hashSync, le pasamos el string, le pasamos el salt y you con eso tenemos nuestro password encriptado y seguro. Por último, lo que vamos a hacer es agregar la comparación, como te decÃa antes, de los passwords, ¿no? Entonces vamos a hacer el validPassword, función, vamos a pasarle un password, y aquà lo que vamos a hacer es usamos el mismo módulo bcrypt compareSync password this.password. Entonces, ¿qué hacemos esto? A un usuario, esto lo vamos a usar en el login, ¿no? Vamos a preguntarle si el password es válido, entonces, ¿cómo le vamos a preguntar? Le vamos a pasar el string del password que querramos y lo vamos a comparar con el bcrypt y lo vamos a comparar, con el módulo este. ¿Por qué? Porque este string va a ser un string plano, lo encriptamos y lo comparamos con la encriptación del mismo password. Si coincide perfecto, estamos en buen camino. Si no coincide estaremos en problemas y buscaremos cómo resolverlo, identificaremos que el usuario no corresponde y listo. [MÚSICA] [MÚSICA]