﻿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,090
‫and so that again is eslint helping me to fix some bugs.

71
00:04:19,090 --> 00:04:20,710
‫So I see that up here, again,

72
00:04:20,710 --> 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,060 --> 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.

