In this video we're going to write out some code to automate this salting and hashing process.
So let's get to it.
I'm gonna open up my user dot J.S. file inside of here.
I'm going to find my user schema and then right underneath it we're gonna add in an additional call.
We're gonna say user schema dot pre and we're gonna pass in a first argument of save and a second argument
of a function like so.
So this is what I referred to as a priest save hook.
In other words this is a function that's going to run before we attempt to actually save an instance
of a user into our database.
So inside of here we're gonna write out some code to look at the password currently attached to a user.
And if it is a plain text password we're then going to attempt to generate that salt we're gonna salt
first we were going to hash the salt and the password together and then we will store the actual result
inside of our database.
Now you'll notice that when I define this safe hook right here I passed in a function with a function
keyword rather than a normal ERO function like so the reason for that is that inside of this function
are user instance in other words the user that we're trying to save is available as this if we make
use of the arrow function inside of here then the value of this will be changed to the context of this
inside of this file which is not what we want we want to get access to the user we're trying to save
which is why we have to use a keyword function instead so inside of here we're gonna first get a reference
to that user or essentially just rename that variable to something more reasonable than this.
We'll first do a quick check.
We're gonna say if the user did not modify their password so user is modified let me get that spelling
modify.
There we go.
Password.
So in other words if the password has not been changed tied to this user whatsoever then we just want
to give up and continue on.
So to give up we're going to receive an argument in this function called next.
Very similar to that next function that we had inside of our middleware.
So inside the if statement will say return next.
So once again this is saying if the user has not modified their password in any way then just don't
try to salt anything after that will start to go through that process of generating a salt and then
hashing it to generate the salt in-house it hash it.
We need to import the B crypto library that we installed a little bit earlier inside this application.
So at the very top I'm going to add in a require statement for secret
then back down here.
We're going to call decrypt dot Jen salt.
We're gonna pass in 10 and we'll give it a callback of error and salt this number right here is essentially
a reference to how complex the salt is that we're going to generate if you want understand more about
the salt.
Feel free to look it up.
There's a ton documentation on decrypt and exactly how it's used.
So then inside of here we're going to check to see if there was an error during the process of generating
our salt so we'll say if there is an error let's just give up.
Once again we're going to return.
We're going to call next and pass in the air that was generated otherwise if we successfully generated
a salt and remember that is a random string of characters then we're going to call decrypt we're going
to hash the user dot password.
So that's gonna be the password that was provided when a user first signs up.
The second argument we'll put in the salt.
Remember that's the random string of characters that we're going to use to prevent that rainbow attack
and we'll put in a callback that's going to be called after this hashing process is complete.
So the callback will be invoked with an air object and the resulting hash will once again check to see
if there was an error.
So if there was an error will return next with that error otherwise we're going to update the user's
password.
So I'll say user dot password is now the hash so we've now overwritten that plain text password and
replaced it with the salted and passed password instead.
Now that we've done all that work we can call next finally and continue on with the saving process and
actually save our user now let's just step one.
This is what's going to hash insults her password.
Step two we need to make sure that we have some functionality to take in some password whenever users
trying to log in.
Remember whenever a user tries to log in.
Where's our diagram.
Here it is right here.
Whenever user logs in they're going to provide us some password that they're trying to use to log in
with.
So we need to run that password through our hashing algorithm and then compare the two results.
We could obviously write all this code directly into a request handler but it makes a lot more sense
to type this code to our user model instead.
So underneath our user schema we will add in some code to automate that password checking process to
do so.
We're going to attach a method to our user model.
I'm going to write out inside of your user schema not methods dot compare a password and then I'll sign
this a function notice that I'm once again using the keyword function right here.
That's because inside this function the value of this is going to be equal to the user we are operating
on.
If we use a aero function instead the value of this will be set to the context of this file which once
again is not what we want it's going to make sure that I provide a function using the function keyword.
This function will then be called with some password that we want to test like a password that the user
is trying to log in with.
So I'm going to accept that as an argument that I'll call candidate password candidate password.
I once again just means that this is what the user is trying to log in with.
So then inside of here we're going to return a new promise.
So we're going to assemble a promise ourselves whenever we create a promise.
We pass it a callback function that function is going to be invoked automatically with two arguments
of resolve and reject.
If some code inside of here behaves as expected we will call resolve and that will resolve the entire
promise.
Otherwise if something goes wrong we will call reject instead and that will reject the promise.
The only reason we are creating a promise ourselves here is so we can make use of the async awaits attacks
whenever we tried to compare a password the decrypt library that we're going to use for the actual comparison
relies upon callbacks entirely which is not super nice.
The secret library using callbacks is kind of an artifact of nodes heritage where we used to rely upon
callbacks quite a bit but these days we really like to use that async await syntax instead.
Once again that's why we're making a promise here and returning that.
Then inside of here.
We will use the secret library to automate that password comparison process.
So we're going to call decrypt dot compare the first argument is going to the function that they use
or assuming the password that the user is trying to log in with.
So for us that would be the candidate password they'll put in candidate password.
Like so the second argument will be these salted and hashed password that we stored inside of our database.
Now once again inside this function the value of this is equal to our user model.
So we can once again kind of pull off a reference to that user so we'll say const user is this like
so.
So then our existing password we will pass in as the second argument with user dot password.
Again that is our salted and hash password that is stored inside of Mongo DB.
And then finally as the third argument we're going to pass in a callback function this will be called
with some era object and a boolean.
So either true or false of is match if it matches true well then as you might guess the Kennedy password
and these salted in hash password are the same set inside of here we can compare and see if we have
an error or if these two things actually matched up.
So false first I'll say if there was an error then let's return early and we will reject the overall
promise with the error that occurred
otherwise if it was not a match.
So if not match like so we're going to again return early and we're going to reject with the value of
false to say sorry but these passwords did not match up so then finally if we got past those two checks
right there that means that is match is true the two passwords did did lineup.
So finally we can resolve with true which is going to successfully resolve our promise and say yep looks
good all these things lined up correctly okay.
That's pretty much it.
So let's now take a quick pause when we come back the next video we're going to take a look at how we're
going to actually make use of this computer password method.
So quick pause and I'll see you in just a minute.