﻿1
00:00:01,190 --> 00:00:03,320
‫In this video and the next ones,

2
00:00:03,320 --> 00:00:05,380
‫we are going to implement a user-friendly

3
00:00:05,380 --> 00:00:08,670
‫password reset functionality, which is kind of

4
00:00:08,670 --> 00:00:11,253
‫standard in most web applications.

5
00:00:12,750 --> 00:00:15,390
‫And probably, you have used the password reset

6
00:00:15,390 --> 00:00:17,720
‫on some website before and usually,

7
00:00:17,720 --> 00:00:19,140
‫it works like this.

8
00:00:19,140 --> 00:00:21,280
‫You just have to provide your email address

9
00:00:21,280 --> 00:00:23,490
‫and you will then get an email with a link

10
00:00:23,490 --> 00:00:25,950
‫where you can click and then that's gonna take you

11
00:00:25,950 --> 00:00:29,410
‫to a page where you can put in a new password.

12
00:00:29,410 --> 00:00:32,270
‫This is a very standard procedure and so

13
00:00:32,270 --> 00:00:34,160
‫this is also how we're going to implement it

14
00:00:34,160 --> 00:00:35,890
‫here in this application.

15
00:00:35,890 --> 00:00:37,700
‫Basically there are two steps.

16
00:00:37,700 --> 00:00:40,930
‫For the first one is that the user sends a post request

17
00:00:40,930 --> 00:00:45,260
‫to a forgot password route, only with this email address.

18
00:00:45,260 --> 00:00:47,510
‫This will then create a reset token

19
00:00:47,510 --> 00:00:50,830
‫and sent that to the email address that was provided.

20
00:00:50,830 --> 00:00:54,930
‫Just a simple, random token, not a JSON Web Token.

21
00:00:54,930 --> 00:00:56,610
‫That's a difference here.

22
00:00:56,610 --> 00:00:59,507
‫Then in the second part, which is gonna be the next video,

23
00:00:59,507 --> 00:01:02,800
‫the user then sends that token from his email

24
00:01:02,800 --> 00:01:06,553
‫along with a new password in order to update his password.

25
00:01:08,040 --> 00:01:13,040
‫Basically, we will have exports dot forgot password

26
00:01:14,810 --> 00:01:16,173
‫which is the first step.

27
00:01:17,930 --> 00:01:22,930
‫So request, response and next

28
00:01:25,560 --> 00:01:28,703
‫and then as a second step, we have reset password.

29
00:01:33,480 --> 00:01:37,260
‫Then let's also go ahead and implement these two routes.

30
00:01:37,260 --> 00:01:40,520
‫Okay, and that's, of course, in their user router

31
00:01:40,520 --> 00:01:42,053
‫or user routes file.

32
00:01:43,190 --> 00:01:45,640
‫Let's put them also right up here

33
00:01:45,640 --> 00:01:48,793
‫and actually I can just duplicate these lines here.

34
00:01:51,131 --> 00:01:54,593
‫So we have again forgot password,

35
00:01:55,820 --> 00:01:58,170
‫which will only receive the email address

36
00:01:58,170 --> 00:02:03,170
‫and then reset password,

37
00:02:03,260 --> 00:02:06,983
‫which will receive the token as well as the new password.

38
00:02:09,360 --> 00:02:10,530
‫This is the one that we're gonna start

39
00:02:10,530 --> 00:02:13,220
‫implementing in this lecture.

40
00:02:13,220 --> 00:02:17,570
‫Let's just like before specify our steps here.

41
00:02:17,570 --> 00:02:20,510
‫So first, get user

42
00:02:23,180 --> 00:02:25,890
‫based on posted email

43
00:02:29,590 --> 00:02:32,383
‫then generate the random token.

44
00:02:37,090 --> 00:02:40,043
‫And then basically send it back as an email.

45
00:02:45,910 --> 00:02:48,793
‫This stuff is pretty common for us at this point.

46
00:02:49,680 --> 00:02:54,397
‫So user, so let's await user dot find

47
00:02:55,330 --> 00:02:57,650
‫and now it's find one,

48
00:02:57,650 --> 00:03:00,920
‫not find by id because we don't know the user's id.

49
00:03:00,920 --> 00:03:04,240
‫And user, of course, also doesn't know his own id

50
00:03:04,240 --> 00:03:06,733
‫and so we specified the email address.

51
00:03:08,390 --> 00:03:11,363
‫Basically it's the only piece of data that is known.

52
00:03:12,230 --> 00:03:16,823
‫And that is stand on request dot body dot email address.

53
00:03:18,723 --> 00:03:20,580
‫And of course now we need to say that

54
00:03:20,580 --> 00:03:25,390
‫we're in an async function and then just like before,

55
00:03:25,390 --> 00:03:27,183
‫let's wrap it in catch async.

56
00:03:30,690 --> 00:03:33,263
‫Give it a save and the error should be gone.

57
00:03:35,280 --> 00:03:36,710
‫Then next step, let's verify

58
00:03:36,710 --> 00:03:38,103
‫if the user does exist.

59
00:03:39,160 --> 00:03:44,160
‫So if no user, then return to the next middleware

60
00:03:48,950 --> 00:03:51,790
‫along of course with a new error.

61
00:03:51,790 --> 00:03:56,790
‫Is no user with that email address.

62
00:03:59,190 --> 00:04:02,510
‫And then we can put a 404, which as you already know,

63
00:04:02,510 --> 00:04:04,023
‫means not found.

64
00:04:05,567 --> 00:04:09,310
‫Next up, let's then generate the random token

65
00:04:09,310 --> 00:04:11,600
‫and for that, once more, we're actually gonna create

66
00:04:11,600 --> 00:04:14,610
‫an instant method on the user.

67
00:04:14,610 --> 00:04:17,430
‫Because once more, this really has to do with

68
00:04:17,430 --> 00:04:19,183
‫the user data itself.

69
00:04:20,280 --> 00:04:22,660
‫And we're gonna write a bit of code really,

70
00:04:22,660 --> 00:04:25,160
‫and so, if it was only one line of code,

71
00:04:25,160 --> 00:04:27,600
‫then of course we could just put it right here.

72
00:04:27,600 --> 00:04:29,540
‫But we need a couple of lines of code

73
00:04:29,540 --> 00:04:31,830
‫and so again, it's a bit cleaner

74
00:04:31,830 --> 00:04:34,080
‫to separate it into its own function.

75
00:04:34,080 --> 00:04:37,823
‫And that usually with Mongoose is best as an instant method.

76
00:04:40,500 --> 00:04:45,490
‫So down here, let's just edit here at the end.

77
00:04:45,490 --> 00:04:50,490
‫So user schema dot methods dot create password reset token.

78
00:04:57,900 --> 00:04:59,950
‫Quite a long and descriptive name.

79
00:04:59,950 --> 00:05:02,020
‫I like to do it like that,

80
00:05:02,020 --> 00:05:05,253
‫so that I know exactly what I'm dealing with.

81
00:05:07,600 --> 00:05:11,690
‫The password reset token should basically be a random string

82
00:05:11,690 --> 00:05:13,650
‫but at the same time, it doesn't need

83
00:05:13,650 --> 00:05:17,250
‫to be as cryptographically strong as the password hash

84
00:05:17,250 --> 00:05:18,433
‫that we created before.

85
00:05:19,640 --> 00:05:22,720
‫We can just use the very simple, random bytes function

86
00:05:22,720 --> 00:05:25,083
‫from the built-in crypto module.

87
00:05:27,350 --> 00:05:30,173
‫Let's go ahead and actually add that.

88
00:05:35,620 --> 00:05:40,620
‫Crypto require and again, it is a built-in a node module

89
00:05:40,870 --> 00:05:43,203
‫so no need to install anything.

90
00:05:44,700 --> 00:05:45,800
‫Cool.

91
00:05:45,800 --> 00:05:50,800
‫Now, let's then actually generate our token.

92
00:05:56,576 --> 00:05:59,913
‫And for that, we use crypto dot random bytes

93
00:06:02,440 --> 00:06:04,750
‫and then here we need to specify the number of

94
00:06:04,750 --> 00:06:05,893
‫characters basically.

95
00:06:07,490 --> 00:06:09,530
‫And then we also in the end,

96
00:06:09,530 --> 00:06:11,823
‫convert it to a hexadecimal string.

97
00:06:14,045 --> 00:06:14,910
‫Two string

98
00:06:17,020 --> 00:06:20,723
‫and then we can specify the hex option here.

99
00:06:22,060 --> 00:06:23,690
‫Now if you're wondering why we are

100
00:06:23,690 --> 00:06:25,360
‫actually creating this token,

101
00:06:25,360 --> 00:06:28,710
‫I guess I didn't really explain it just yet.

102
00:06:28,710 --> 00:06:31,170
‫Basically this token is what we're gonna send

103
00:06:31,170 --> 00:06:34,660
‫to the user and so it's like a reset password really

104
00:06:34,660 --> 00:06:38,610
‫that the user can then use to create a new real password.

105
00:06:38,610 --> 00:06:41,690
‫And of course, only the user will have access to this token.

106
00:06:41,690 --> 00:06:45,363
‫And so in fact, it really behaves kind of like a password.

107
00:06:45,363 --> 00:06:48,380
‫Since essentially it is just a password,

108
00:06:48,380 --> 00:06:52,210
‫it means that if a hacker can get access to our database,

109
00:06:52,210 --> 00:06:55,000
‫well then that's gonna allow the hacker to gain access

110
00:06:55,000 --> 00:06:57,483
‫to the account by setting a new password.

111
00:06:59,474 --> 00:07:01,740
‫If we would just simply store this reset token

112
00:07:01,740 --> 00:07:05,160
‫in our database now, then if some attacker gains access

113
00:07:05,160 --> 00:07:07,200
‫to the database, they could then use

114
00:07:07,200 --> 00:07:10,090
‫that token and create a new password using that token

115
00:07:10,090 --> 00:07:11,690
‫instead of you doing it.

116
00:07:11,690 --> 00:07:14,120
‫They would then effectively control your account

117
00:07:14,120 --> 00:07:15,563
‫instead of you doing it.

118
00:07:16,810 --> 00:07:19,150
‫Just like a password, we should never store

119
00:07:19,150 --> 00:07:21,933
‫a plain reset token in the database.

120
00:07:23,030 --> 00:07:24,670
‫Let's actually encrypt it,

121
00:07:24,670 --> 00:07:26,880
‫but such as before with the password,

122
00:07:26,880 --> 00:07:29,670
‫it doesn't need such a cryptographically strong

123
00:07:29,670 --> 00:07:30,803
‫encryption method.

124
00:07:31,640 --> 00:07:34,653
‫Because these reset tokens are a way less dangerous

125
00:07:34,653 --> 00:07:35,993
‫attack vector.

126
00:07:37,050 --> 00:07:39,230
‫Again, we're just gonna use the built-in

127
00:07:39,230 --> 00:07:40,233
‫crypto module.

128
00:07:41,610 --> 00:07:44,213
‫It works in this kind of weird-looking way.

129
00:07:45,420 --> 00:07:48,740
‫We say crypto then create hash

130
00:07:51,170 --> 00:07:54,550
‫with the sha 256 algorithm

131
00:07:55,750 --> 00:07:57,560
‫then we need to say update

132
00:07:57,560 --> 00:08:00,593
‫and then variable where the token is stored.

133
00:08:01,840 --> 00:08:04,340
‫Whatever string we want to encrypt basically.

134
00:08:04,340 --> 00:08:08,570
‫And then we need to say digest and then again

135
00:08:08,570 --> 00:08:10,433
‫store it as a hexadecimal.

136
00:08:12,950 --> 00:08:16,660
‫And now where are we actually gonna save this reset token?

137
00:08:16,660 --> 00:08:19,883
‫Well, we're gonna create a new field in our database schema.

138
00:08:20,886 --> 00:08:23,340
‫'Cause of course, we want to save it in the database,

139
00:08:23,340 --> 00:08:24,940
‫so that we can then compare it

140
00:08:24,940 --> 00:08:27,003
‫with the token that the user provides.

141
00:08:30,037 --> 00:08:30,870
‫Let's do that here at the end.

142
00:08:34,599 --> 00:08:36,349
‫Password reset token,

143
00:08:39,884 --> 00:08:41,248
‫that's the string.

144
00:08:41,248 --> 00:08:44,331
‫And then also password reset expires.

145
00:08:49,890 --> 00:08:51,780
‫Because this reset will actually expire

146
00:08:51,780 --> 00:08:56,100
‫after a certain amount of time as a security measure.

147
00:08:56,100 --> 00:08:58,820
‫You will only have 10 minutes in order to actually

148
00:08:58,820 --> 00:09:00,133
‫reset your password.

149
00:09:03,850 --> 00:09:05,500
‫Let's now go ahead and use these.

150
00:09:06,950 --> 00:09:11,950
‫This dot password reset token is then equal

151
00:09:13,440 --> 00:09:14,843
‫to this encryption.

152
00:09:19,270 --> 00:09:23,720
‫Next up, let's then set password reset expires

153
00:09:24,570 --> 00:09:29,400
‫and let's set that to date dot now

154
00:09:29,400 --> 00:09:32,193
‫and then simply add a couple of seconds to that.

155
00:09:33,510 --> 00:09:35,910
‫We want it to work for 10 minutes

156
00:09:35,910 --> 00:09:40,093
‫and so that's 10 and then we need it in milliseconds.

157
00:09:41,270 --> 00:09:46,270
‫Times 60 for seconds and then times 1000 for milliseconds.

158
00:09:49,124 --> 00:09:52,320
‫And then I also want to return the plain text token

159
00:09:52,320 --> 00:09:54,770
‫because that's actually the one that we're gonna send

160
00:09:54,770 --> 00:09:55,783
‫through the email.

161
00:09:58,080 --> 00:10:01,863
‫Return reset token.

162
00:10:06,345 --> 00:10:08,860
‫We need to send via email

163
00:10:08,860 --> 00:10:11,660
‫the unencrypted reset token because otherwise

164
00:10:11,660 --> 00:10:14,503
‫it wouldn't make much sense to encrypt it at all.

165
00:10:15,430 --> 00:10:17,090
‫If the token that was in the database

166
00:10:17,090 --> 00:10:19,290
‫was the exact same that we could use

167
00:10:19,290 --> 00:10:20,980
‫to actually change the password,

168
00:10:20,980 --> 00:10:23,643
‫well then that wouldn't be any encryption at all.

169
00:10:24,640 --> 00:10:26,417
‫We sent one token via email

170
00:10:26,417 --> 00:10:29,420
‫and then we have the encrypted version in our database.

171
00:10:29,420 --> 00:10:32,210
‫And that encrypted one is then basically useless

172
00:10:32,210 --> 00:10:34,050
‫to change the password.

173
00:10:34,050 --> 00:10:36,250
‫It's just like when we're saving only the

174
00:10:36,250 --> 00:10:39,470
‫encrypted password itself to the database,

175
00:10:39,470 --> 00:10:43,230
‫just like we did up here,

176
00:10:43,230 --> 00:10:46,967
‫So where we encrypted the password using bcrypt.

177
00:10:48,439 --> 00:10:51,100
‫Keep in mind that the only ever save

178
00:10:51,100 --> 00:10:53,680
‫sensitive data in an encrypted form

179
00:10:53,680 --> 00:10:56,620
‫and then compare it with the encrypted version

180
00:10:56,620 --> 00:10:57,770
‫that's in the database.

181
00:11:00,385 --> 00:11:02,500
‫That's just log these two to the console

182
00:11:02,500 --> 00:11:06,730
‫that will make our lives a bit easier down the road.

183
00:11:06,730 --> 00:11:09,630
‫Let's say reset token

184
00:11:10,470 --> 00:11:11,440
‫and I'm logging in here

185
00:11:11,440 --> 00:11:14,930
‫as an object because this way, it will then actually

186
00:11:14,930 --> 00:11:17,803
‫tell me the variable name along with its value.

187
00:11:20,210 --> 00:11:25,153
‫And then the same with this dot password reset token.

188
00:11:28,030 --> 00:11:29,880
‫This one doesn't really work

189
00:11:29,880 --> 00:11:32,340
‫with writing object, this new ES6 way

190
00:11:32,340 --> 00:11:34,140
‫and let's just leave it at this.

191
00:11:36,550 --> 00:11:38,080
‫Anyway, let's just come back here

192
00:11:38,080 --> 00:11:40,153
‫and then use that function.

193
00:11:41,660 --> 00:11:44,930
‫So remember how we returned the reset token,

194
00:11:44,930 --> 00:11:46,653
‫and let's store that here.

195
00:11:48,040 --> 00:11:52,873
‫So reset token is equal to user dot set

196
00:11:54,370 --> 00:11:56,373
‫and I'm not sure of the name anymore.

197
00:11:58,500 --> 00:12:00,560
‫Create password reset token,

198
00:12:00,560 --> 00:12:01,633
‫so that's a long one.

199
00:12:03,430 --> 00:12:06,240
‫All right and so that is done,

200
00:12:06,240 --> 00:12:09,460
‫but actually what we did was just to modify

201
00:12:09,460 --> 00:12:10,943
‫the data in here.

202
00:12:12,780 --> 00:12:16,580
‫When we set this dot password expires for example

203
00:12:16,580 --> 00:12:19,040
‫to this value, we did in fact

204
00:12:19,040 --> 00:12:20,880
‫not really update the document.

205
00:12:20,880 --> 00:12:22,063
‫We did not save it.

206
00:12:23,100 --> 00:12:24,880
‫We really just modify it,

207
00:12:24,880 --> 00:12:27,563
‫but now we then need to save it.

208
00:12:29,950 --> 00:12:34,653
‫Let's say await user dot save.

209
00:12:36,750 --> 00:12:39,583
‫But watch what happens as we now use this.

210
00:12:43,910 --> 00:12:46,463
‫Let's just grab this one here.

211
00:12:50,980 --> 00:12:53,080
‫This is the route that we did find before.

212
00:12:54,440 --> 00:12:57,750
‫And now we get this route is not yet defined.

213
00:12:57,750 --> 00:12:59,413
‫Let's see why that is.

214
00:13:00,290 --> 00:13:04,740
‫In the user route, we clearly have the same url here,

215
00:13:04,740 --> 00:13:08,463
‫but I see that we actually need to do a post request.

216
00:13:09,390 --> 00:13:13,380
‫All right, okay, but now we get an error

217
00:13:13,380 --> 00:13:16,200
‫saying please provide email and password.

218
00:13:16,200 --> 00:13:18,320
‫And so that's what I meant when I said

219
00:13:18,320 --> 00:13:20,343
‫watch what happens when you try this.

220
00:13:21,990 --> 00:13:25,330
‫That happens because we're trying to save a document,

221
00:13:25,330 --> 00:13:28,860
‫but we do not specify all of the mandatory data,

222
00:13:28,860 --> 00:13:31,453
‫so the fields that we marked as required.

223
00:13:32,502 --> 00:13:34,683
‫Let's quickly fix that.

224
00:13:35,848 --> 00:13:38,888
‫All we need to do is to actually pass a special option

225
00:13:38,888 --> 00:13:41,643
‫into this user dot save method.

226
00:13:43,140 --> 00:13:43,973
‫We say

227
00:13:47,210 --> 00:13:48,720
‫validate before save

228
00:13:49,890 --> 00:13:51,293
‫set to false.

229
00:13:52,332 --> 00:13:55,260
‫This will then deactivate all the validaters

230
00:13:55,260 --> 00:13:56,993
‫that we specified in our schema.

231
00:13:58,540 --> 00:14:01,100
‫It's these small things that you need to know

232
00:14:01,100 --> 00:14:02,800
‫that will make all the difference.

233
00:14:03,790 --> 00:14:06,570
‫Now I also didn't actually know that this existed

234
00:14:06,570 --> 00:14:09,170
‫because no one really knows all of the stuff.

235
00:14:09,170 --> 00:14:10,260
‫It's impossible.

236
00:14:10,260 --> 00:14:13,010
‫A library like Mongoose is simply way too big

237
00:14:13,010 --> 00:14:14,833
‫for you to know everything there is.

238
00:14:16,010 --> 00:14:19,020
‫I went ahead and read the Mongoose documentation

239
00:14:19,020 --> 00:14:22,710
‫and so that's where I found this extremely helpful option.

240
00:14:22,710 --> 00:14:25,050
‫All of this just to say that again,

241
00:14:25,050 --> 00:14:26,520
‫no one knows everything

242
00:14:26,520 --> 00:14:28,520
‫and so it's really a good habit to

243
00:14:28,520 --> 00:14:29,960
‫if you run into some problems

244
00:14:29,960 --> 00:14:31,830
‫to take a look at the documentation

245
00:14:31,830 --> 00:14:34,210
‫for the library that you're using.

246
00:14:34,210 --> 00:14:35,963
‫Let's take a look at this now.

247
00:14:39,410 --> 00:14:42,260
‫And we still get the same error here,

248
00:14:42,260 --> 00:14:43,890
‫but I see down here that it's actually

249
00:14:43,890 --> 00:14:45,883
‫coming from the login function.

250
00:14:48,210 --> 00:14:50,573
‫Let's take a look at what's going on here.

251
00:14:51,490 --> 00:14:54,550
‫Let's take a look at the routes also.

252
00:14:54,550 --> 00:14:56,343
‫Ah, okay, so here's the problem.

253
00:14:57,610 --> 00:14:59,420
‫We are now trying to call

254
00:14:59,420 --> 00:15:02,170
‫the login handler, which of course, doesn't make sense.

255
00:15:03,660 --> 00:15:05,790
‫Here it's forgot password.

256
00:15:05,790 --> 00:15:07,633
‫Here it's reset password.

257
00:15:08,850 --> 00:15:12,290
‫And so the error that we got before was actually not because

258
00:15:12,290 --> 00:15:13,463
‫of the validation.

259
00:15:16,312 --> 00:15:17,980
‫Let's send this again

260
00:15:17,980 --> 00:15:20,100
‫and now we get the error that there is no user

261
00:15:20,100 --> 00:15:21,420
‫with this email address

262
00:15:21,420 --> 00:15:24,140
‫and so that's because we didn't specify

263
00:15:24,140 --> 00:15:26,103
‫any email address in the body.

264
00:15:28,390 --> 00:15:29,680
‫We tested that

265
00:15:29,680 --> 00:15:32,300
‫and so now it's time to actually test it

266
00:15:32,300 --> 00:15:34,093
‫with a user email.

267
00:15:43,409 --> 00:15:44,440
‫All right.

268
00:15:44,440 --> 00:15:46,380
‫And so now it shouldn't actually do anything

269
00:15:46,380 --> 00:15:49,320
‫because we're not sending back any response.

270
00:15:49,320 --> 00:15:50,700
‫Let's just cancel this

271
00:15:50,700 --> 00:15:52,540
‫because all I was really interested in

272
00:15:52,540 --> 00:15:55,227
‫is to see these tokens here

273
00:15:55,227 --> 00:15:57,830
‫and then also to take a look at the user object.

274
00:15:57,830 --> 00:16:01,050
‫This here is the original reset token,

275
00:16:01,050 --> 00:16:04,150
‫so you see it's a random hexadecimal string

276
00:16:04,150 --> 00:16:06,593
‫and then we got the encrypted one in here.

277
00:16:07,840 --> 00:16:11,330
‫This remember is the one that should not be in the database,

278
00:16:11,330 --> 00:16:13,663
‫so ending in a901.

279
00:16:14,930 --> 00:16:16,230
‫Let's take a look at that.

280
00:16:18,410 --> 00:16:20,460
‫And indeed, here it is,

281
00:16:20,460 --> 00:16:24,740
‫password reset token ending in this a901.

282
00:16:24,740 --> 00:16:28,960
‫And also the date, which is in fact 10 minutes from now.

283
00:16:28,960 --> 00:16:31,753
‫Now you know at what time I'm recording this video.

284
00:16:33,130 --> 00:16:35,340
‫Anyway, but this worked just fine.

285
00:16:35,340 --> 00:16:37,890
‫And so this is actually the first part

286
00:16:37,890 --> 00:16:41,561
‫of creating this password reset functionality.

287
00:16:41,561 --> 00:16:43,140
‫In the next video, we will then

288
00:16:43,140 --> 00:16:46,840
‫send this token here via email to the user

289
00:16:46,840 --> 00:16:49,500
‫and so actually prepared a separate video

290
00:16:49,500 --> 00:16:52,370
‫only for learning how to actually send email with

291
00:16:52,370 --> 00:16:53,470
‫node to js.

292
00:16:53,470 --> 00:16:55,100
‫That's a very fun one

293
00:16:55,100 --> 00:16:58,363
‫so don't wait to move there right away.

