Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
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,279 --> 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.
22674
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.