All language subtitles for 007 Logging in Users_Downloadly.ir_en

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranî)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
fa Persian Download
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu
Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated: 1 00:00:01,260 --> 00:00:02,480 So in this lecture 2 00:00:02,480 --> 00:00:04,560 we're gonna implement the functionality 3 00:00:04,560 --> 00:00:08,010 of logging users in based on a given password 4 00:00:08,010 --> 00:00:09,363 and email address. 5 00:00:10,920 --> 00:00:14,520 And just like before, the concept of logging a user in 6 00:00:14,520 --> 00:00:17,400 basically means to sign a JSON web token 7 00:00:17,400 --> 00:00:19,760 and send it back to the client. 8 00:00:19,760 --> 00:00:22,390 But in this case we only issue the token 9 00:00:22,390 --> 00:00:24,860 in case that the user actually exists, 10 00:00:24,860 --> 00:00:27,310 and that the password is correct. 11 00:00:27,310 --> 00:00:29,773 So, let's start to implement that. 12 00:00:31,480 --> 00:00:36,260 Exports.login is... 13 00:00:39,090 --> 00:00:42,253 request, responds, and next. 14 00:00:44,370 --> 00:00:47,060 And the first thing is we is to actually read the email 15 00:00:47,060 --> 00:00:50,020 and the password from the body. 16 00:00:50,020 --> 00:00:54,740 So let's say const email equals req.body.email. 17 00:00:58,920 --> 00:01:02,070 Okay, and now eslint gives us this warning, 18 00:01:02,070 --> 00:01:04,160 or this error actually, and it says 19 00:01:04,160 --> 00:01:07,080 that we should use object destructuring, okay? 20 00:01:07,080 --> 00:01:09,620 And so I let this happen here on purpose 21 00:01:09,620 --> 00:01:12,620 just so that I can show you how we can do it 22 00:01:12,620 --> 00:01:14,950 with ES6 destructuring. 23 00:01:14,950 --> 00:01:18,490 And I think I talked about this before in the course, 24 00:01:18,490 --> 00:01:20,930 and I also hope that you're already familiar 25 00:01:20,930 --> 00:01:23,330 with the concept, but anyway, 26 00:01:23,330 --> 00:01:25,430 since the name of this property here 27 00:01:25,430 --> 00:01:27,920 is the same as the variable name, 28 00:01:27,920 --> 00:01:30,260 we can simply do it like this 29 00:01:30,260 --> 00:01:34,150 and get rid of the property name here, okay? 30 00:01:34,150 --> 00:01:36,520 And also we want to get the password. 31 00:01:36,520 --> 00:01:37,930 And so that would be the same, 32 00:01:37,930 --> 00:01:42,470 so basically password equals to a request.body.password. 33 00:01:42,470 --> 00:01:43,647 And instead of doing that, 34 00:01:43,647 --> 00:01:47,940 we can simply do email and password. 35 00:01:47,940 --> 00:01:50,250 And so just like this, we basically create 36 00:01:50,250 --> 00:01:54,480 these two variables of the body object, okay? 37 00:01:54,480 --> 00:01:56,380 So basically this is how the user 38 00:01:56,380 --> 00:02:00,223 is gonna send in the login credentials for us to check. 39 00:02:01,070 --> 00:02:04,130 Okay, and that check process has a couple of steps, 40 00:02:04,130 --> 00:02:05,830 and so let's actually lay them out here 41 00:02:05,830 --> 00:02:07,750 before we start coding. 42 00:02:07,750 --> 00:02:12,030 So first we need to check if email 43 00:02:12,030 --> 00:02:17,030 and passwords actually exist, all right? 44 00:02:17,900 --> 00:02:22,900 Then number two, check if the user exists, 45 00:02:24,440 --> 00:02:29,440 and at the same time if the password is correct. 46 00:02:31,960 --> 00:02:33,943 And then third, if everything is okay, 47 00:02:39,440 --> 00:02:44,440 send the token, so the JSON web token back to the client. 48 00:02:45,800 --> 00:02:48,490 Okay, so the first one is very easy. 49 00:02:48,490 --> 00:02:53,490 So if there is no email or no password, 50 00:02:56,810 --> 00:03:00,370 then we want to send an error message to our client. 51 00:03:00,370 --> 00:03:02,600 Now how are we gonna do that? 52 00:03:02,600 --> 00:03:04,490 Well we're gonna do that using the tools 53 00:03:04,490 --> 00:03:07,490 that we implemented right in the last section. 54 00:03:07,490 --> 00:03:10,730 So basically our app error, remember that? 55 00:03:10,730 --> 00:03:12,977 So we will simply create a new error here, 56 00:03:12,977 --> 00:03:15,060 and our global error handling middleware 57 00:03:15,060 --> 00:03:19,190 will then pick it up and send that error back to the client. 58 00:03:19,190 --> 00:03:22,483 And so let's actually start by importing that error. 59 00:03:23,350 --> 00:03:25,260 So remember it's this one here 60 00:03:25,260 --> 00:03:28,463 from our AppError class, right? 61 00:03:29,620 --> 00:03:34,620 So let's say AppError, and then require. 62 00:03:40,860 --> 00:03:44,150 So one level up from here, then in the utilities, 63 00:03:44,150 --> 00:03:45,050 and then appError. 64 00:03:48,990 --> 00:03:52,430 Okay, and so we need to call the next middleware, 65 00:03:52,430 --> 00:03:56,403 and then this is where we pass in the error, remember that? 66 00:03:57,260 --> 00:04:00,363 So new AppError, and the message is: 67 00:04:02,510 --> 00:04:07,510 please provide email and password. 68 00:04:07,530 --> 00:04:12,530 And the HTTP error code is 400 for bad request, okay? 69 00:04:12,720 --> 00:04:14,340 And now I've got some errors here, 70 00:04:14,340 --> 00:04:19,089 and so that again is eslint helping me to fix some bugs. 71 00:04:19,089 --> 00:04:20,709 So I see that up here, again, 72 00:04:20,709 --> 00:04:24,010 I used it with a T instead of D, 73 00:04:24,010 --> 00:04:27,740 and if I save it now, everything is correct. 74 00:04:27,740 --> 00:04:32,393 Okay, and so let's actually start testing this right away. 75 00:04:33,330 --> 00:04:34,700 And for that I will simply start 76 00:04:34,700 --> 00:04:39,700 by creating a fake token here for now, okay. 77 00:04:39,930 --> 00:04:43,287 And so then let's say res.status 200 for okay. 78 00:04:51,202 --> 00:04:53,573 JSON, and then of course, as always, 79 00:04:56,540 --> 00:05:01,010 the status set to success, and then also our token. 80 00:05:01,010 --> 00:05:02,870 And that's actually all that we're gonna send 81 00:05:02,870 --> 00:05:05,130 as a response to the login, okay? 82 00:05:05,130 --> 00:05:08,290 So no user object because that's not necessary at all. 83 00:05:08,290 --> 00:05:10,800 All we want as a response for logging in 84 00:05:10,800 --> 00:05:12,140 is actually the token. 85 00:05:12,140 --> 00:05:15,033 That's all that matters when the user logs in. 86 00:05:16,210 --> 00:05:18,960 Next up, we need to implement the route, 87 00:05:18,960 --> 00:05:23,600 so let's do that again in our user router, okay? 88 00:05:23,600 --> 00:05:27,000 And this one is actually pretty similar to this one. 89 00:05:27,000 --> 00:05:30,310 Let's just duplicate it and then replace signup 90 00:05:30,310 --> 00:05:34,780 in both instances here with login, okay? 91 00:05:34,780 --> 00:05:38,220 And again, this is only valid for a post request, 92 00:05:38,220 --> 00:05:40,360 because of course we want to send in 93 00:05:40,360 --> 00:05:43,200 the login credentials in the body. 94 00:05:43,200 --> 00:05:44,630 And so again it's a post, 95 00:05:44,630 --> 00:05:47,610 but not a get, not a patch, and not a delete, 96 00:05:47,610 --> 00:05:50,393 because that doesn't make any sense in this case. 97 00:05:51,590 --> 00:05:54,033 So let's test it right away. 98 00:05:54,970 --> 00:05:57,033 I'll copy this URL here as well. 99 00:05:58,050 --> 00:06:03,050 It's gonna be post, login, 100 00:06:03,570 --> 00:06:05,140 and then the body of course. 101 00:06:05,140 --> 00:06:08,700 So again, raw and JSON. 102 00:06:08,700 --> 00:06:11,443 So let's create a simple body here. 103 00:06:17,680 --> 00:06:19,960 All right, and so let's try to send this 104 00:06:19,960 --> 00:06:22,993 without any password, and see what happens. 105 00:06:24,460 --> 00:06:27,470 And indeed it works, so we get our message here: 106 00:06:27,470 --> 00:06:30,030 please provide email and password. 107 00:06:30,030 --> 00:06:31,820 And again, since we're in development, 108 00:06:31,820 --> 00:06:34,110 we're getting all of this error stack here, 109 00:06:34,110 --> 00:06:36,910 and the complete error with our status code, 110 00:06:36,910 --> 00:06:39,350 the status, and also of course saying 111 00:06:39,350 --> 00:06:41,330 that it is an operational error. 112 00:06:41,330 --> 00:06:45,840 So just like we defined in the previous section, okay? 113 00:06:45,840 --> 00:06:48,433 Now let's try the same with the password. 114 00:06:50,750 --> 00:06:55,750 So password, set it to I think this was the one, 115 00:06:56,400 --> 00:06:58,893 and then get rid of the email. 116 00:07:00,590 --> 00:07:02,950 And that of course triggers the same. 117 00:07:02,950 --> 00:07:06,000 Okay, and with everything correct that should then work, 118 00:07:06,000 --> 00:07:08,803 and indeed we get our fake token here. 119 00:07:10,300 --> 00:07:12,890 Now just one thing that we should do here 120 00:07:12,890 --> 00:07:14,880 is to also return. 121 00:07:14,880 --> 00:07:16,790 So we did that many times before, 122 00:07:16,790 --> 00:07:18,680 and let me explain it again. 123 00:07:18,680 --> 00:07:21,610 It's simply because after calling the next middleware, 124 00:07:21,610 --> 00:07:24,380 we want to make sure that this login function here 125 00:07:24,380 --> 00:07:27,873 finishes right away, all right? 126 00:07:30,260 --> 00:07:32,080 And since we didn't have that before, 127 00:07:32,080 --> 00:07:34,560 you now see this error here again. 128 00:07:34,560 --> 00:07:38,060 So this is already kind of familiar at this point, right? 129 00:07:38,060 --> 00:07:40,940 So cannot set headers after they are send to the client, 130 00:07:40,940 --> 00:07:43,360 because again, we sent two responses. 131 00:07:43,360 --> 00:07:47,840 First the error response, and then also this code here run, 132 00:07:47,840 --> 00:07:50,040 which of course shouldn't have done. 133 00:07:50,040 --> 00:07:52,933 And so again we use return here to fix that. 134 00:07:53,790 --> 00:07:57,430 Okay, next up, let's check if there actually is a user 135 00:07:57,430 --> 00:07:59,870 for the email that was posted. 136 00:07:59,870 --> 00:08:04,870 So const user, and so let's now use the findOne actually, 137 00:08:09,940 --> 00:08:13,400 because this time we're not selecting a user by the ID, 138 00:08:13,400 --> 00:08:16,650 but instead by its email, right? 139 00:08:16,650 --> 00:08:19,460 And so we need to pass in that filter object 140 00:08:19,460 --> 00:08:24,190 where we can say email equal to email, okay? 141 00:08:24,190 --> 00:08:25,940 So the field is called email, 142 00:08:25,940 --> 00:08:28,270 and the variable is also called email. 143 00:08:28,270 --> 00:08:32,163 And so in ES6 we can abbreviate that simply as this. 144 00:08:33,059 --> 00:08:34,490 Now before we move on here, 145 00:08:34,490 --> 00:08:36,110 there's actually something important 146 00:08:36,110 --> 00:08:38,520 that I need to do for security. 147 00:08:38,520 --> 00:08:41,220 So let me show that to you in Postman, 148 00:08:41,220 --> 00:08:43,970 where we signed up for a new account. 149 00:08:43,970 --> 00:08:46,540 And so you see here that in the user output, 150 00:08:46,540 --> 00:08:49,810 we actually get the password, okay? 151 00:08:49,810 --> 00:08:52,010 It is encrypted actually, but still, 152 00:08:52,010 --> 00:08:55,010 it's not a good practice to leak the password data 153 00:08:55,010 --> 00:08:57,710 out to the client, okay? 154 00:08:57,710 --> 00:09:01,090 For example, if we had our get all users here, 155 00:09:01,090 --> 00:09:03,480 and this route is not yet implemented, 156 00:09:03,480 --> 00:09:07,170 but if we were to get all the users from the collection, 157 00:09:07,170 --> 00:09:09,440 then all of them would have the password visible, 158 00:09:09,440 --> 00:09:12,720 and we don't want that, okay? 159 00:09:12,720 --> 00:09:15,790 And so fixing it is actually quite easy, 160 00:09:15,790 --> 00:09:17,850 because we did it before. 161 00:09:17,850 --> 00:09:19,973 All we have to do is to say password, 162 00:09:20,820 --> 00:09:25,270 and then select and set it to false. 163 00:09:25,270 --> 00:09:28,100 And so like this it will automatically never show up 164 00:09:28,100 --> 00:09:29,123 in any output. 165 00:09:30,520 --> 00:09:32,520 And to let me actually prove that to you 166 00:09:32,520 --> 00:09:37,023 by signing up as something else, so like this. 167 00:09:39,070 --> 00:09:41,920 And let's see, oh, actually we already have a user 168 00:09:41,920 --> 00:09:45,833 with that email, so let's just do test3. 169 00:09:47,300 --> 00:09:50,830 And now the password is actually still here, 170 00:09:50,830 --> 00:09:54,100 but I guess that is simply because we could just create it, 171 00:09:54,100 --> 00:09:55,610 this new document here, 172 00:09:55,610 --> 00:09:58,030 and so therefore it's not really selecting it 173 00:09:58,030 --> 00:10:01,460 because we're not actually reading it from the database. 174 00:10:01,460 --> 00:10:03,250 So let's just very quickly 175 00:10:03,250 --> 00:10:05,100 actually implement this route here, 176 00:10:05,100 --> 00:10:07,690 that's only gonna take a minute. 177 00:10:07,690 --> 00:10:10,300 So just to see if this here actually works. 178 00:10:10,300 --> 00:10:12,230 Because this step is actually important 179 00:10:12,230 --> 00:10:15,170 for what we're gonna do next, okay? 180 00:10:15,170 --> 00:10:18,820 So let's actually go ahead and copy this code 181 00:10:18,820 --> 00:10:22,000 from the getAllTours, and not really copy, 182 00:10:22,000 --> 00:10:25,133 but what we're gonna do is quite similar to this of course. 183 00:10:26,750 --> 00:10:28,590 So I'm simply gonna copy this, 184 00:10:28,590 --> 00:10:30,450 but without the API features. 185 00:10:30,450 --> 00:10:33,700 So I'm not really interested in that, okay? 186 00:10:33,700 --> 00:10:35,500 And so this one I'm actually gonna do 187 00:10:35,500 --> 00:10:39,170 in the user controller, because getting all the users 188 00:10:39,170 --> 00:10:41,350 has nothing to do with authentication. 189 00:10:41,350 --> 00:10:43,570 And so in this case the user controller 190 00:10:43,570 --> 00:10:47,020 is the perfect place for doing this. 191 00:10:47,020 --> 00:10:49,440 Now of course I also need to quickly import 192 00:10:49,440 --> 00:10:51,990 the user model here, and so let's also copy that 193 00:10:51,990 --> 00:10:56,580 from the tourController, which is not the same but similar. 194 00:10:56,580 --> 00:11:00,550 So let's grab actually all of this 195 00:11:04,200 --> 00:11:06,370 into our user controller. 196 00:11:06,370 --> 00:11:09,683 This one we don't need, but we also need to catchAsync. 197 00:11:10,520 --> 00:11:13,640 Okay, so tour is gonna be user, 198 00:11:13,640 --> 00:11:18,400 and here it will be userModel, all right? 199 00:11:18,400 --> 00:11:21,420 Then here we have tours, and down here and down here, 200 00:11:21,420 --> 00:11:23,790 so I hit Command + D to select all of them 201 00:11:23,790 --> 00:11:26,033 and change it to users. 202 00:11:27,190 --> 00:11:32,190 And then here of course what we are awaiting is User.find. 203 00:11:34,870 --> 00:11:36,320 Now since we have an await here, 204 00:11:36,320 --> 00:11:41,310 we need async, then we also need next, 205 00:11:41,310 --> 00:11:42,810 and since we have an async here, 206 00:11:42,810 --> 00:11:46,580 we should then wrap the entire thing into a catch async. 207 00:11:46,580 --> 00:11:47,713 So let's do that. 208 00:11:50,090 --> 00:11:51,700 Okay, and so at this point 209 00:11:51,700 --> 00:11:53,810 this is nothing new to you anymore, 210 00:11:53,810 --> 00:11:58,120 we're already used to doing this kind of stuff, right? 211 00:11:58,120 --> 00:12:00,670 So, this should already work at this point, 212 00:12:00,670 --> 00:12:02,470 so let's try it out. 213 00:12:02,470 --> 00:12:06,460 So get all users, and now indeed we see 214 00:12:06,460 --> 00:12:10,030 that their password is not included in the output. 215 00:12:10,030 --> 00:12:13,853 And that is important because actually, in the find, 216 00:12:15,090 --> 00:12:17,093 so back here in the AuthController, 217 00:12:18,030 --> 00:12:21,490 this here will now also not contain the password, okay? 218 00:12:21,490 --> 00:12:23,060 And so the output of this here 219 00:12:23,060 --> 00:12:25,920 will now also not contain the password. 220 00:12:25,920 --> 00:12:28,890 But we do need the password in order to check 221 00:12:28,890 --> 00:12:30,810 if it is correct, right? 222 00:12:30,810 --> 00:12:34,500 And so we need to explicitly select it as well. 223 00:12:34,500 --> 00:12:37,460 So remember how we used select before 224 00:12:37,460 --> 00:12:40,150 to basically simply select a couple of fields 225 00:12:40,150 --> 00:12:43,450 from the database, only the ones that we needed? 226 00:12:43,450 --> 00:12:45,460 Now in this case, when we want the field 227 00:12:45,460 --> 00:12:47,640 that is by default not selected, 228 00:12:47,640 --> 00:12:50,853 we need to user plus and then the name of the field. 229 00:12:51,720 --> 00:12:53,610 So password in this case. 230 00:12:53,610 --> 00:12:58,220 And so like this, it will be back in the output, okay? 231 00:12:58,220 --> 00:13:01,750 Of course we need to await this query, 232 00:13:01,750 --> 00:13:06,260 and then mark the function as async. 233 00:13:06,260 --> 00:13:08,140 And then just like before, 234 00:13:08,140 --> 00:13:12,010 in order to avoid that ugly try catch block, 235 00:13:12,010 --> 00:13:16,253 wrap this entire function into catchAsync. 236 00:13:18,520 --> 00:13:20,163 All right, makes sense? 237 00:13:22,170 --> 00:13:26,770 So let's now quickly just log the user to the console, 238 00:13:26,770 --> 00:13:28,353 just to see if it works. 239 00:13:32,220 --> 00:13:34,033 So this one here. 240 00:13:35,460 --> 00:13:39,600 We get our success, and indeed we get the user here. 241 00:13:39,600 --> 00:13:42,650 So with exactly the email that I just posted, 242 00:13:42,650 --> 00:13:45,830 and then the password is now also back to being included 243 00:13:45,830 --> 00:13:47,890 in the output, all right? 244 00:13:47,890 --> 00:13:51,453 And so again, that's because we explicitly selected it here. 245 00:13:52,490 --> 00:13:54,950 And so now it's time to actually compare 246 00:13:54,950 --> 00:13:57,400 the passwords that we have in the database 247 00:13:57,400 --> 00:13:59,830 with the one that the user just posted. 248 00:13:59,830 --> 00:14:01,930 But how are we gonna do that? 249 00:14:01,930 --> 00:14:05,190 Because for example, the password might be, 250 00:14:05,190 --> 00:14:09,169 or is in this example, pass1234, but the one 251 00:14:09,169 --> 00:14:13,983 that we have stored in the document looks like this. 252 00:14:15,040 --> 00:14:17,220 So how are we gonna compare this? 253 00:14:17,220 --> 00:14:19,960 There's not really a way of doing it, right? 254 00:14:19,960 --> 00:14:22,300 But actually there is, all we have to do 255 00:14:22,300 --> 00:14:25,890 is to again use the bcrypt package, okay? 256 00:14:25,890 --> 00:14:29,400 So we used bcrypt to generate this hashed password, 257 00:14:29,400 --> 00:14:31,230 and we can also use the same package 258 00:14:31,230 --> 00:14:34,930 to basically compare an original password like this here 259 00:14:34,930 --> 00:14:36,283 with the hashed password. 260 00:14:37,230 --> 00:14:40,700 Of course this password here, since it's encrypted, 261 00:14:40,700 --> 00:14:43,350 there's no way of getting back the old, 262 00:14:43,350 --> 00:14:46,680 so the original password from this string, right? 263 00:14:46,680 --> 00:14:48,150 So that's the entire point 264 00:14:48,150 --> 00:14:50,550 of actually encrypting a password. 265 00:14:50,550 --> 00:14:52,410 And so the only way of doing it 266 00:14:52,410 --> 00:14:54,890 is for this package for this algorithm 267 00:14:54,890 --> 00:14:58,100 to actually encrypt this password as well, 268 00:14:58,100 --> 00:15:02,210 and then compare it with the encrypted one, all right? 269 00:15:02,210 --> 00:15:05,110 So let's implement a function that's gonna do that, 270 00:15:05,110 --> 00:15:08,350 and for that we will use, again, the bcrypt package. 271 00:15:08,350 --> 00:15:11,280 And we will do that in the user model. 272 00:15:11,280 --> 00:15:13,767 And you might ask "Why we're doing it in a model 273 00:15:13,767 --> 00:15:16,310 "and not just here," but that's, again, 274 00:15:16,310 --> 00:15:19,730 because this is really related to the data itself. 275 00:15:19,730 --> 00:15:22,930 And also we already have that package in there, 276 00:15:22,930 --> 00:15:26,090 and so it's easier to simply do it there. 277 00:15:26,090 --> 00:15:28,663 So let's just get rid of this string, 278 00:15:30,600 --> 00:15:32,360 and then create a function here, 279 00:15:32,360 --> 00:15:34,580 which will check if the given password 280 00:15:34,580 --> 00:15:37,473 is the same as the one stored in the document. 281 00:15:38,520 --> 00:15:41,100 So for the first time now we're gonna create something 282 00:15:41,100 --> 00:15:43,000 called an instance method. 283 00:15:43,000 --> 00:15:46,120 So an instance method is basically a method 284 00:15:46,120 --> 00:15:48,500 that is gonna be available on all documents 285 00:15:48,500 --> 00:15:50,843 of a certain collection, okay? 286 00:15:51,680 --> 00:15:53,320 And it works like this. 287 00:15:53,320 --> 00:15:56,120 So again, it's defined on a userSchema, 288 00:15:56,120 --> 00:16:01,050 and then we say methods, and now in this case 289 00:16:01,050 --> 00:16:05,273 we want to call the function correctPassword, all right? 290 00:16:10,340 --> 00:16:12,810 So function, now this function is gonna accept 291 00:16:12,810 --> 00:16:14,470 a candidatePassword, so the password 292 00:16:17,734 --> 00:16:19,650 that the user passes in the body, 293 00:16:19,650 --> 00:16:22,347 and then also the userPassword, okay? 294 00:16:26,010 --> 00:16:28,590 Now inside of these instanced methods, 295 00:16:28,590 --> 00:16:31,470 since they are available on the document, 296 00:16:31,470 --> 00:16:35,430 the this keyword actually points to the current document. 297 00:16:35,430 --> 00:16:37,610 But in this case, since we have the password 298 00:16:37,610 --> 00:16:42,080 set to select false, so this here, remember? 299 00:16:42,080 --> 00:16:43,690 Okay, and because of that, 300 00:16:43,690 --> 00:16:47,920 this.password will not be available. 301 00:16:47,920 --> 00:16:50,780 So ideally we would do it like this, 302 00:16:50,780 --> 00:16:52,360 and so this way we would only need 303 00:16:52,360 --> 00:16:56,130 to pass in the candidatePassword and not the userPassword. 304 00:16:56,130 --> 00:16:58,690 But again, right now that's not possible 305 00:16:58,690 --> 00:17:02,350 because the password is not available in the output. 306 00:17:02,350 --> 00:17:03,420 And so that's why we actually 307 00:17:03,420 --> 00:17:06,380 have to pass in userPassword as well. 308 00:17:06,380 --> 00:17:07,890 So the goal of this function 309 00:17:07,890 --> 00:17:11,030 is to really only return true or false. 310 00:17:11,030 --> 00:17:14,000 So basically true if the passwords are the same, 311 00:17:14,000 --> 00:17:15,663 and false if not. 312 00:17:16,560 --> 00:17:21,410 So return, and then bcrypt which we already know, 313 00:17:21,410 --> 00:17:26,257 and then we are gonna use the compare function, okay? 314 00:17:26,257 --> 00:17:29,190 And the compare function is really easy, 315 00:17:29,190 --> 00:17:32,200 all we need is to pass in the candidatePassword 316 00:17:32,200 --> 00:17:37,060 and the userPassword, not userSchema, userPassword, okay? 317 00:17:39,270 --> 00:17:42,090 And just like the hash function up here, 318 00:17:42,090 --> 00:17:45,383 this one is also an asynchronous function. 319 00:17:46,270 --> 00:17:50,973 And so just like before we use await, and then here async. 320 00:17:53,330 --> 00:17:54,940 Okay, make sense? 321 00:17:54,940 --> 00:17:57,630 So again, this compare function here 322 00:17:57,630 --> 00:17:59,800 will very simply return true 323 00:17:59,800 --> 00:18:04,470 if these two passwords here are the same, and false if not. 324 00:18:04,470 --> 00:18:07,030 And again, we cannot compare them manually 325 00:18:07,030 --> 00:18:10,020 because the candidate password is not hashed, 326 00:18:10,020 --> 00:18:12,800 so it's the original password coming from the user, 327 00:18:12,800 --> 00:18:15,580 but userPassword is of course hashed, 328 00:18:15,580 --> 00:18:18,230 and so without this function here 329 00:18:18,230 --> 00:18:21,830 we would have no way of comparing them, okay? 330 00:18:21,830 --> 00:18:23,990 So here we return true or false, 331 00:18:23,990 --> 00:18:26,893 now all we need to do is to actually call this function 332 00:18:26,893 --> 00:18:28,633 in the authController. 333 00:18:29,920 --> 00:18:31,873 Let's close a couple of these. 334 00:18:34,080 --> 00:18:38,253 All right, so this here was only here for demonstration. 335 00:18:41,400 --> 00:18:43,563 So let's simply call this here correct, 336 00:18:44,400 --> 00:18:47,110 and now remember that the function that we just defined 337 00:18:47,110 --> 00:18:48,670 is an instanced method. 338 00:18:48,670 --> 00:18:52,260 And so therefore it is available on all the user documents. 339 00:18:52,260 --> 00:18:54,780 And so this variable here right now 340 00:18:54,780 --> 00:18:57,050 is a user document, right? 341 00:18:57,050 --> 00:19:00,270 Because it's a result of querying the user model. 342 00:19:00,270 --> 00:19:03,637 And so we can now say user.correctPassword. 343 00:19:06,760 --> 00:19:10,650 Now all we need to do is pass in the candidate password, 344 00:19:10,650 --> 00:19:13,020 which is password, remember. 345 00:19:13,020 --> 00:19:17,830 So this one here, and then the userPassword. 346 00:19:17,830 --> 00:19:22,830 And so that's in user.password, all right? 347 00:19:23,450 --> 00:19:26,373 And so this here will now be either true or false. 348 00:19:27,990 --> 00:19:30,810 All right, and now let's actually use these two variables 349 00:19:30,810 --> 00:19:33,500 in order to figure out if the user exists 350 00:19:33,500 --> 00:19:35,200 and the password is correct. 351 00:19:35,200 --> 00:19:36,710 So we already figured that out, 352 00:19:36,710 --> 00:19:40,390 but now we need to actually write our if statement. 353 00:19:40,390 --> 00:19:45,390 So if there is no user, or the password is incorrect, 354 00:19:46,160 --> 00:19:49,853 so basically correct is false, which is what this means. 355 00:19:50,860 --> 00:19:54,590 In that case, we want to, again, 356 00:19:54,590 --> 00:19:58,640 return and go straight to our next middleware 357 00:19:58,640 --> 00:19:59,640 with a new AppError. 358 00:20:00,980 --> 00:20:05,973 And in this case saying incorrect email or password, okay? 359 00:20:08,990 --> 00:20:11,560 And then the status code is 401, 360 00:20:11,560 --> 00:20:14,870 which means unauthorized, all right? 361 00:20:14,870 --> 00:20:16,910 Now we could've done this separately, 362 00:20:16,910 --> 00:20:18,847 so first checking for the user, 363 00:20:18,847 --> 00:20:21,440 and then checking for the correct password. 364 00:20:21,440 --> 00:20:24,600 But in that case we would then give a potential attacker 365 00:20:24,600 --> 00:20:28,710 information whether the email or the password is incorrect. 366 00:20:28,710 --> 00:20:31,550 And this way here it's a bit more vague. 367 00:20:31,550 --> 00:20:34,830 So we're not really specifying what is incorrect here. 368 00:20:34,830 --> 00:20:37,060 So if it's email or if it's the password. 369 00:20:37,060 --> 00:20:38,700 And so if there's some attacker 370 00:20:38,700 --> 00:20:41,150 trying to put in some random data, 371 00:20:41,150 --> 00:20:43,640 then they will not know if the email actually exists, 372 00:20:43,640 --> 00:20:47,143 or if it's just the password that's wrong, all right? 373 00:20:47,990 --> 00:20:50,860 Now just two things here, and the first one 374 00:20:50,860 --> 00:20:53,140 is that we actually need to await 375 00:20:53,140 --> 00:20:55,480 this asynchronous function, okay? 376 00:20:55,480 --> 00:20:57,470 So remember that correct password 377 00:20:57,470 --> 00:20:59,000 is an asynchronous function, 378 00:20:59,000 --> 00:21:01,333 and so here we also need to await for that. 379 00:21:02,690 --> 00:21:04,530 And then also there's another problem, 380 00:21:04,530 --> 00:21:06,980 because of this user doesn't exist here, 381 00:21:06,980 --> 00:21:10,950 then this next line of code cannot really run, okay? 382 00:21:10,950 --> 00:21:13,550 Because for example, user.password 383 00:21:13,550 --> 00:21:15,400 is not gonna be available. 384 00:21:15,400 --> 00:21:18,800 And so we actually need to move all of this, 385 00:21:18,800 --> 00:21:20,690 or actually only this code, 386 00:21:20,690 --> 00:21:24,343 we're gonna move it here into the if else statement. 387 00:21:26,740 --> 00:21:29,000 All right, and so this way, 388 00:21:29,000 --> 00:21:32,550 if the user does not exist, so if this is true, 389 00:21:32,550 --> 00:21:34,900 well then it will not even run this code here, 390 00:21:34,900 --> 00:21:37,070 and then there's not gonna be any problem. 391 00:21:37,070 --> 00:21:40,510 But if the user exists, then it will also run this code 392 00:21:40,510 --> 00:21:43,600 and check if the password is actually right. 393 00:21:43,600 --> 00:21:45,520 And so if the password is correct, 394 00:21:45,520 --> 00:21:50,010 only in that case we ever reach this piece of code here. 395 00:21:50,010 --> 00:21:52,710 So that's the whole idea of this function. 396 00:21:52,710 --> 00:21:55,030 So basically we check for the negatives. 397 00:21:55,030 --> 00:21:57,270 So if there's no email and no password, 398 00:21:57,270 --> 00:21:58,880 then we get this error. 399 00:21:58,880 --> 00:22:01,690 If there's no user, or if there's a wrong password, 400 00:22:01,690 --> 00:22:03,540 then create this error. 401 00:22:03,540 --> 00:22:05,610 But if there was no error at all, 402 00:22:05,610 --> 00:22:09,060 well in that case we reach this part of the code, 403 00:22:09,060 --> 00:22:10,820 where we now generate a token 404 00:22:10,820 --> 00:22:13,490 and then send it back to the user. 405 00:22:13,490 --> 00:22:16,740 Now creating this token is gonna be the exact same thing 406 00:22:16,740 --> 00:22:18,500 as we did before here. 407 00:22:18,500 --> 00:22:20,780 And so instead of repeating all of this code, 408 00:22:20,780 --> 00:22:24,210 let's actually create a function for this, okay? 409 00:22:24,210 --> 00:22:25,840 So I'm gonna copy this code, 410 00:22:25,840 --> 00:22:29,427 and then here very quickly const signToken, 411 00:22:31,900 --> 00:22:36,090 which is gonna receive as the only input the user ID. 412 00:22:36,090 --> 00:22:41,090 So ID, and it will then return the token, okay? 413 00:22:43,370 --> 00:22:46,793 So it will simply sign this and return it right away. 414 00:22:47,700 --> 00:22:50,920 All right, and so here what we're gonna do 415 00:22:50,920 --> 00:22:55,920 is signToken and pass in this ID. 416 00:23:04,970 --> 00:23:09,330 And then of course we also need to change it up here, okay? 417 00:23:09,330 --> 00:23:11,750 So set this ID to this ID, 418 00:23:11,750 --> 00:23:14,893 which as you already know at this point is the same as this. 419 00:23:15,950 --> 00:23:19,763 All right, and so let's now go ahead and do the same here. 420 00:23:22,547 --> 00:23:26,340 signToken, and then in this case it is user._id. 421 00:23:31,300 --> 00:23:33,910 Phew, that was a long lecture, 422 00:23:33,910 --> 00:23:37,090 let's now go ahead and try it out. 423 00:23:37,090 --> 00:23:38,363 So it should now work. 424 00:23:39,250 --> 00:23:43,470 So remember, well this is now another user, 425 00:23:43,470 --> 00:23:46,030 but I know that this is the password that I used. 426 00:23:46,030 --> 00:23:48,580 So let's for now let's use another one, 427 00:23:48,580 --> 00:23:52,003 so just test12, and let's see what happens. 428 00:23:53,540 --> 00:23:57,450 Let's wait, and indeed, incorrect email or password. 429 00:23:57,450 --> 00:24:00,230 And so we get of course also our 401, 430 00:24:00,230 --> 00:24:04,600 and indeed it means that our code is currently testing 431 00:24:04,600 --> 00:24:05,933 for the password already. 432 00:24:06,780 --> 00:24:10,230 So if we now choose the correct password, 433 00:24:10,230 --> 00:24:12,793 then it should pass, so let's wait for it. 434 00:24:13,760 --> 00:24:16,760 But, we still get this error. 435 00:24:16,760 --> 00:24:20,453 Well, so let's simply get rid of all of our users here, 436 00:24:22,170 --> 00:24:24,420 just to make sure that it doesn't have to do anything 437 00:24:24,420 --> 00:24:28,740 with the users, and then create a new one, all right. 438 00:24:33,080 --> 00:24:37,473 So hello@jonas, and pass1234. 439 00:24:38,710 --> 00:24:42,373 Let's go ahead and copy it, I will send it now. 440 00:24:46,800 --> 00:24:50,070 And so these credentials are now correct for sure. 441 00:24:50,070 --> 00:24:52,760 So if it doesn't work now there's some kind of bug. 442 00:24:52,760 --> 00:24:55,870 But now actually it worked, great. 443 00:24:55,870 --> 00:25:00,090 So here is our token, and it looks exactly like before, 444 00:25:00,090 --> 00:25:02,483 so we can assume that it is correct. 445 00:25:03,570 --> 00:25:06,333 Now let's now try it again, deleting this, okay. 446 00:25:07,810 --> 00:25:10,753 And so with the wrong password it does not work. 447 00:25:11,890 --> 00:25:15,423 Let's now put the password right and the email wrong, 448 00:25:18,230 --> 00:25:19,730 and then we get the same error. 449 00:25:19,730 --> 00:25:21,883 So incorrect email or password. 450 00:25:22,930 --> 00:25:25,560 And again if we put everything back, 451 00:25:25,560 --> 00:25:27,560 then we get a new token. 452 00:25:27,560 --> 00:25:30,810 And so we are now really logged into the application. 453 00:25:30,810 --> 00:25:33,580 And I know this might look kind of abstract, 454 00:25:33,580 --> 00:25:37,340 so all we really get is a token, and then that means 455 00:25:37,340 --> 00:25:40,020 we are logged into the application, right? 456 00:25:40,020 --> 00:25:44,720 But, well, that's how it works on stateless authentication. 457 00:25:44,720 --> 00:25:47,810 Later on when we really build the dynamic website, 458 00:25:47,810 --> 00:25:50,190 then of course it's gonna be a lot more visible 459 00:25:50,190 --> 00:25:53,900 if the user is either logged in or logged out, right? 460 00:25:53,900 --> 00:25:55,920 But it will still work behind the scenes 461 00:25:55,920 --> 00:25:57,670 using this same token. 462 00:25:57,670 --> 00:26:01,560 So if there's no token, then the website will look one way, 463 00:26:01,560 --> 00:26:03,800 and if there is a token then the website's 464 00:26:03,800 --> 00:26:06,630 gonna look another way, with the user image 465 00:26:06,630 --> 00:26:11,150 and the username right there in the website, for example. 466 00:26:11,150 --> 00:26:13,373 Anyway, this was quite a long lecture. 467 00:26:14,370 --> 00:26:17,100 Make sure to go back here and really try to understand 468 00:26:17,100 --> 00:26:20,210 all of this code that we have here, all right? 469 00:26:20,210 --> 00:26:21,870 Because I know that some of this 470 00:26:21,870 --> 00:26:23,660 might be a bit confusing. 471 00:26:23,660 --> 00:26:26,963 For example, this correctPassword function here. 472 00:26:27,850 --> 00:26:30,933 And then I'm sure everything will make sense to you. 38003

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.