1 00:00:01,050 --> 00:00:04,890 In this video we're going to write out some code to automate this salting and hashing process. 2 00:00:04,890 --> 00:00:06,090 So let's get to it. 3 00:00:06,780 --> 00:00:09,870 I'm gonna open up my user dot J.S. file inside of here. 4 00:00:09,880 --> 00:00:14,200 I'm going to find my user schema and then right underneath it we're gonna add in an additional call. 5 00:00:14,200 --> 00:00:22,120 We're gonna say user schema dot pre and we're gonna pass in a first argument of save and a second argument 6 00:00:22,180 --> 00:00:24,830 of a function like so. 7 00:00:24,880 --> 00:00:27,870 So this is what I referred to as a priest save hook. 8 00:00:27,880 --> 00:00:32,350 In other words this is a function that's going to run before we attempt to actually save an instance 9 00:00:32,350 --> 00:00:34,380 of a user into our database. 10 00:00:34,420 --> 00:00:39,190 So inside of here we're gonna write out some code to look at the password currently attached to a user. 11 00:00:39,400 --> 00:00:44,740 And if it is a plain text password we're then going to attempt to generate that salt we're gonna salt 12 00:00:44,850 --> 00:00:49,330 first we were going to hash the salt and the password together and then we will store the actual result 13 00:00:49,570 --> 00:00:51,570 inside of our database. 14 00:00:51,570 --> 00:00:55,930 Now you'll notice that when I define this safe hook right here I passed in a function with a function 15 00:00:55,930 --> 00:01:02,740 keyword rather than a normal ERO function like so the reason for that is that inside of this function 16 00:01:03,330 --> 00:01:09,760 are user instance in other words the user that we're trying to save is available as this if we make 17 00:01:09,760 --> 00:01:15,370 use of the arrow function inside of here then the value of this will be changed to the context of this 18 00:01:15,400 --> 00:01:19,810 inside of this file which is not what we want we want to get access to the user we're trying to save 19 00:01:20,170 --> 00:01:25,530 which is why we have to use a keyword function instead so inside of here we're gonna first get a reference 20 00:01:25,530 --> 00:01:29,860 to that user or essentially just rename that variable to something more reasonable than this. 21 00:01:30,170 --> 00:01:31,830 We'll first do a quick check. 22 00:01:31,830 --> 00:01:41,180 We're gonna say if the user did not modify their password so user is modified let me get that spelling 23 00:01:41,180 --> 00:01:41,780 modify. 24 00:01:41,780 --> 00:01:42,730 There we go. 25 00:01:42,860 --> 00:01:43,460 Password. 26 00:01:43,460 --> 00:01:47,960 So in other words if the password has not been changed tied to this user whatsoever then we just want 27 00:01:47,960 --> 00:01:50,010 to give up and continue on. 28 00:01:50,150 --> 00:01:53,760 So to give up we're going to receive an argument in this function called next. 29 00:01:53,780 --> 00:01:57,010 Very similar to that next function that we had inside of our middleware. 30 00:01:57,050 --> 00:02:00,320 So inside the if statement will say return next. 31 00:02:00,320 --> 00:02:05,540 So once again this is saying if the user has not modified their password in any way then just don't 32 00:02:05,540 --> 00:02:11,960 try to salt anything after that will start to go through that process of generating a salt and then 33 00:02:12,020 --> 00:02:15,110 hashing it to generate the salt in-house it hash it. 34 00:02:15,140 --> 00:02:20,660 We need to import the B crypto library that we installed a little bit earlier inside this application. 35 00:02:20,720 --> 00:02:24,470 So at the very top I'm going to add in a require statement for secret 36 00:02:28,030 --> 00:02:29,530 then back down here. 37 00:02:29,530 --> 00:02:32,770 We're going to call decrypt dot Jen salt. 38 00:02:33,070 --> 00:02:39,990 We're gonna pass in 10 and we'll give it a callback of error and salt this number right here is essentially 39 00:02:39,990 --> 00:02:45,480 a reference to how complex the salt is that we're going to generate if you want understand more about 40 00:02:45,480 --> 00:02:46,010 the salt. 41 00:02:46,020 --> 00:02:47,220 Feel free to look it up. 42 00:02:47,220 --> 00:02:50,630 There's a ton documentation on decrypt and exactly how it's used. 43 00:02:51,450 --> 00:02:55,320 So then inside of here we're going to check to see if there was an error during the process of generating 44 00:02:55,320 --> 00:02:58,430 our salt so we'll say if there is an error let's just give up. 45 00:02:58,440 --> 00:02:59,930 Once again we're going to return. 46 00:03:00,090 --> 00:03:06,020 We're going to call next and pass in the air that was generated otherwise if we successfully generated 47 00:03:06,050 --> 00:03:12,800 a salt and remember that is a random string of characters then we're going to call decrypt we're going 48 00:03:12,800 --> 00:03:15,620 to hash the user dot password. 49 00:03:15,620 --> 00:03:20,590 So that's gonna be the password that was provided when a user first signs up. 50 00:03:20,790 --> 00:03:22,450 The second argument we'll put in the salt. 51 00:03:22,470 --> 00:03:26,220 Remember that's the random string of characters that we're going to use to prevent that rainbow attack 52 00:03:26,920 --> 00:03:31,750 and we'll put in a callback that's going to be called after this hashing process is complete. 53 00:03:31,870 --> 00:03:38,790 So the callback will be invoked with an air object and the resulting hash will once again check to see 54 00:03:38,790 --> 00:03:39,540 if there was an error. 55 00:03:39,540 --> 00:03:46,500 So if there was an error will return next with that error otherwise we're going to update the user's 56 00:03:46,500 --> 00:03:47,210 password. 57 00:03:47,250 --> 00:03:54,720 So I'll say user dot password is now the hash so we've now overwritten that plain text password and 58 00:03:54,720 --> 00:03:58,610 replaced it with the salted and passed password instead. 59 00:03:58,650 --> 00:04:03,240 Now that we've done all that work we can call next finally and continue on with the saving process and 60 00:04:03,240 --> 00:04:06,800 actually save our user now let's just step one. 61 00:04:06,850 --> 00:04:09,670 This is what's going to hash insults her password. 62 00:04:09,670 --> 00:04:15,180 Step two we need to make sure that we have some functionality to take in some password whenever users 63 00:04:15,190 --> 00:04:16,860 trying to log in. 64 00:04:16,870 --> 00:04:18,940 Remember whenever a user tries to log in. 65 00:04:18,970 --> 00:04:19,660 Where's our diagram. 66 00:04:19,660 --> 00:04:20,590 Here it is right here. 67 00:04:20,620 --> 00:04:24,730 Whenever user logs in they're going to provide us some password that they're trying to use to log in 68 00:04:24,730 --> 00:04:25,030 with. 69 00:04:25,660 --> 00:04:31,660 So we need to run that password through our hashing algorithm and then compare the two results. 70 00:04:31,720 --> 00:04:35,980 We could obviously write all this code directly into a request handler but it makes a lot more sense 71 00:04:35,980 --> 00:04:39,080 to type this code to our user model instead. 72 00:04:39,100 --> 00:04:45,570 So underneath our user schema we will add in some code to automate that password checking process to 73 00:04:45,570 --> 00:04:46,070 do so. 74 00:04:46,080 --> 00:04:49,200 We're going to attach a method to our user model. 75 00:04:49,200 --> 00:04:56,250 I'm going to write out inside of your user schema not methods dot compare a password and then I'll sign 76 00:04:56,250 --> 00:05:00,880 this a function notice that I'm once again using the keyword function right here. 77 00:05:00,890 --> 00:05:05,270 That's because inside this function the value of this is going to be equal to the user we are operating 78 00:05:05,360 --> 00:05:06,100 on. 79 00:05:06,320 --> 00:05:11,750 If we use a aero function instead the value of this will be set to the context of this file which once 80 00:05:11,750 --> 00:05:16,690 again is not what we want it's going to make sure that I provide a function using the function keyword. 81 00:05:17,060 --> 00:05:22,340 This function will then be called with some password that we want to test like a password that the user 82 00:05:22,340 --> 00:05:24,120 is trying to log in with. 83 00:05:24,140 --> 00:05:30,440 So I'm going to accept that as an argument that I'll call candidate password candidate password. 84 00:05:30,460 --> 00:05:33,750 I once again just means that this is what the user is trying to log in with. 85 00:05:34,520 --> 00:05:38,840 So then inside of here we're going to return a new promise. 86 00:05:38,870 --> 00:05:42,550 So we're going to assemble a promise ourselves whenever we create a promise. 87 00:05:42,560 --> 00:05:48,230 We pass it a callback function that function is going to be invoked automatically with two arguments 88 00:05:48,230 --> 00:05:50,600 of resolve and reject. 89 00:05:50,600 --> 00:05:55,340 If some code inside of here behaves as expected we will call resolve and that will resolve the entire 90 00:05:55,340 --> 00:05:56,270 promise. 91 00:05:56,270 --> 00:06:01,220 Otherwise if something goes wrong we will call reject instead and that will reject the promise. 92 00:06:01,250 --> 00:06:05,840 The only reason we are creating a promise ourselves here is so we can make use of the async awaits attacks 93 00:06:06,020 --> 00:06:10,880 whenever we tried to compare a password the decrypt library that we're going to use for the actual comparison 94 00:06:11,090 --> 00:06:16,180 relies upon callbacks entirely which is not super nice. 95 00:06:16,390 --> 00:06:21,620 The secret library using callbacks is kind of an artifact of nodes heritage where we used to rely upon 96 00:06:21,620 --> 00:06:26,160 callbacks quite a bit but these days we really like to use that async await syntax instead. 97 00:06:26,210 --> 00:06:30,040 Once again that's why we're making a promise here and returning that. 98 00:06:30,080 --> 00:06:31,020 Then inside of here. 99 00:06:31,130 --> 00:06:35,960 We will use the secret library to automate that password comparison process. 100 00:06:35,960 --> 00:06:42,350 So we're going to call decrypt dot compare the first argument is going to the function that they use 101 00:06:42,350 --> 00:06:44,830 or assuming the password that the user is trying to log in with. 102 00:06:45,250 --> 00:06:50,010 So for us that would be the candidate password they'll put in candidate password. 103 00:06:50,020 --> 00:06:56,260 Like so the second argument will be these salted and hashed password that we stored inside of our database. 104 00:06:56,260 --> 00:07:01,020 Now once again inside this function the value of this is equal to our user model. 105 00:07:01,570 --> 00:07:05,950 So we can once again kind of pull off a reference to that user so we'll say const user is this like 106 00:07:05,950 --> 00:07:06,810 so. 107 00:07:06,990 --> 00:07:12,150 So then our existing password we will pass in as the second argument with user dot password. 108 00:07:12,160 --> 00:07:17,400 Again that is our salted and hash password that is stored inside of Mongo DB. 109 00:07:17,550 --> 00:07:21,790 And then finally as the third argument we're going to pass in a callback function this will be called 110 00:07:21,790 --> 00:07:24,170 with some era object and a boolean. 111 00:07:24,180 --> 00:07:30,420 So either true or false of is match if it matches true well then as you might guess the Kennedy password 112 00:07:30,720 --> 00:07:37,740 and these salted in hash password are the same set inside of here we can compare and see if we have 113 00:07:37,740 --> 00:07:41,150 an error or if these two things actually matched up. 114 00:07:41,370 --> 00:07:47,640 So false first I'll say if there was an error then let's return early and we will reject the overall 115 00:07:47,640 --> 00:07:50,730 promise with the error that occurred 116 00:07:53,280 --> 00:07:56,420 otherwise if it was not a match. 117 00:07:56,430 --> 00:08:02,820 So if not match like so we're going to again return early and we're going to reject with the value of 118 00:08:02,910 --> 00:08:09,900 false to say sorry but these passwords did not match up so then finally if we got past those two checks 119 00:08:09,900 --> 00:08:14,390 right there that means that is match is true the two passwords did did lineup. 120 00:08:14,400 --> 00:08:20,310 So finally we can resolve with true which is going to successfully resolve our promise and say yep looks 121 00:08:20,310 --> 00:08:23,400 good all these things lined up correctly okay. 122 00:08:23,440 --> 00:08:24,890 That's pretty much it. 123 00:08:24,900 --> 00:08:28,560 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 124 00:08:28,560 --> 00:08:31,740 going to actually make use of this computer password method. 125 00:08:31,740 --> 00:08:34,060 So quick pause and I'll see you in just a minute.