Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:02,150 --> 00:00:03,110
Now that we are able
2
00:00:03,110 --> 00:00:05,320
to create users, it's now time
3
00:00:05,320 --> 00:00:08,840
to work on the authentication functionality.
4
00:00:08,840 --> 00:00:10,800
So on logging users in
5
00:00:10,800 --> 00:00:13,650
and getting that permission, this token
6
00:00:13,650 --> 00:00:15,690
for our logged in users.
7
00:00:15,690 --> 00:00:19,220
And being able to find out if a user is logged in,
8
00:00:19,220 --> 00:00:22,690
both on the client side for changing what we see
9
00:00:22,690 --> 00:00:24,950
and for disabling certain routes,
10
00:00:24,950 --> 00:00:28,980
as well as on the server side in different API routes
11
00:00:28,980 --> 00:00:30,530
we might be adding.
12
00:00:30,530 --> 00:00:33,710
And that's now the part where this NextAuth package,
13
00:00:33,710 --> 00:00:37,380
which we installed earlier already becomes important.
14
00:00:37,380 --> 00:00:40,380
It helps us with authenticating users
15
00:00:40,380 --> 00:00:43,160
and it helps us with finding out
16
00:00:43,160 --> 00:00:45,520
whether a user has that permission
17
00:00:45,520 --> 00:00:49,820
by managing that token creation and storage,
18
00:00:49,820 --> 00:00:52,600
both parts behind the scenes.
19
00:00:52,600 --> 00:00:53,940
Now, to use NextAuth,
20
00:00:53,940 --> 00:00:56,830
we start by adding another API route
21
00:00:56,830 --> 00:01:00,410
because logging a user in, signing a user in,
22
00:01:00,410 --> 00:01:03,740
that, of course, also requires a request
23
00:01:03,740 --> 00:01:06,760
to be sent to a certain API route
24
00:01:06,760 --> 00:01:08,700
where we then look into the database
25
00:01:08,700 --> 00:01:12,660
and find out whether we have that user in the database
26
00:01:12,660 --> 00:01:15,820
and whether the password is correct.
27
00:01:15,820 --> 00:01:18,220
And therefore, I'll create another file
28
00:01:18,220 --> 00:01:21,330
in that api/auth folder
29
00:01:21,330 --> 00:01:25,030
but this file now needs a special name.
30
00:01:25,030 --> 00:01:27,050
It's a square bracket file name.
31
00:01:27,050 --> 00:01:29,800
So a dynamic API route
32
00:01:29,800 --> 00:01:33,150
and it's a dynamic catch all API route,
33
00:01:33,150 --> 00:01:36,660
which catches all unknown routes
34
00:01:36,660 --> 00:01:39,880
that start with api/auth.
35
00:01:39,880 --> 00:01:44,880
Here we can then use ...nextauth written like this.
36
00:01:45,880 --> 00:01:50,880
One word and in here, we now use that NextAuth package.
37
00:01:51,340 --> 00:01:53,730
And we need this catch all route
38
00:01:53,730 --> 00:01:57,350
because the next auth package behind the scenes
39
00:01:57,350 --> 00:02:00,080
will expose multiple routes
40
00:02:00,080 --> 00:02:05,080
for user login and for user logout, for example.
41
00:02:05,380 --> 00:02:07,950
A couple of other routes as well.
42
00:02:07,950 --> 00:02:10,240
And in order to set up its own routes
43
00:02:10,240 --> 00:02:11,830
and handle its own routes,
44
00:02:11,830 --> 00:02:13,690
we need to have a catch all route
45
00:02:13,690 --> 00:02:16,850
so that all those special requests
46
00:02:16,850 --> 00:02:18,530
to these special routes
47
00:02:18,530 --> 00:02:23,170
are automatically handled by the NextAuth package.
48
00:02:23,170 --> 00:02:25,910
We can still also define our own routes,
49
00:02:25,910 --> 00:02:27,890
like the signup route in addition,
50
00:02:27,890 --> 00:02:30,030
as long as we don't override one
51
00:02:30,030 --> 00:02:34,590
of the built-in routes NextAuth exposes.
52
00:02:34,590 --> 00:02:37,820
If you wanna find out which routes it creates,
53
00:02:37,820 --> 00:02:40,530
you can check out the official NextAuth documentation
54
00:02:40,530 --> 00:02:42,450
and click on REST API there
55
00:02:42,450 --> 00:02:45,260
and these are the different routes,
56
00:02:45,260 --> 00:02:48,770
they all start with /api/auth as you can tell,
57
00:02:48,770 --> 00:02:51,010
which will be handled by NextAuth.
58
00:02:51,010 --> 00:02:53,393
So we shouldn't clash with those.
59
00:02:54,810 --> 00:02:57,252
Now, how do we then use NextAuth here?
60
00:02:57,252 --> 00:02:59,260
We, first of all, import it
61
00:02:59,260 --> 00:03:02,470
in this square bracket nextauth.js file.
62
00:03:02,470 --> 00:03:04,120
We import NextAuth from next-auth
63
00:03:06,810 --> 00:03:08,560
and then with this imported,
64
00:03:08,560 --> 00:03:12,890
we export NextAuth as a default
65
00:03:12,890 --> 00:03:15,640
but not like this but we execute it.
66
00:03:15,640 --> 00:03:18,290
So NextAuth here is a function,
67
00:03:18,290 --> 00:03:19,860
which we can execute
68
00:03:19,860 --> 00:03:21,230
and when we execute it,
69
00:03:21,230 --> 00:03:24,810
it returns a new function, a handler function.
70
00:03:24,810 --> 00:03:28,460
It needs to because this is still an API route
71
00:03:28,460 --> 00:03:30,360
and therefore, an API route still needs
72
00:03:30,360 --> 00:03:31,900
to return a function.
73
00:03:31,900 --> 00:03:33,670
It needs to export a function.
74
00:03:33,670 --> 00:03:36,490
But that exported handler function
75
00:03:36,490 --> 00:03:40,233
is created by NextAuth by calling NextAuth.
76
00:03:41,090 --> 00:03:42,980
And when we call NextAuth,
77
00:03:42,980 --> 00:03:46,310
we can pass a configuration object to it.
78
00:03:46,310 --> 00:03:47,960
That's the object which allows us
79
00:03:47,960 --> 00:03:51,210
to configure NextAuth's behavior.
80
00:03:51,210 --> 00:03:53,540
And you can dive into the official docs,
81
00:03:53,540 --> 00:03:57,930
configuration options to learn about all the options you can
82
00:03:57,930 --> 00:03:59,343
and must set here.
83
00:04:00,590 --> 00:04:05,590
Now, in our case, we wanna set the providers option here
84
00:04:05,770 --> 00:04:08,110
and set this to an array.
85
00:04:08,110 --> 00:04:10,710
And here we need to import something else.
86
00:04:10,710 --> 00:04:12,380
We need to import Providers
87
00:04:12,380 --> 00:04:17,380
from next-auth/providers like this
88
00:04:19,240 --> 00:04:21,110
and then here in the providers array,
89
00:04:21,110 --> 00:04:23,320
we use Providers dot
90
00:04:23,320 --> 00:04:25,700
and then here you can choose from the long list
91
00:04:25,700 --> 00:04:27,790
of supported providers.
92
00:04:27,790 --> 00:04:30,510
And again, check out the providers docs
93
00:04:30,510 --> 00:04:32,670
to learn more about the concrete way
94
00:04:32,670 --> 00:04:35,730
of setting up the different providers.
95
00:04:35,730 --> 00:04:38,960
But here, we need the Credentials provider,
96
00:04:38,960 --> 00:04:41,653
which means that we bring our own credentials.
97
00:04:42,520 --> 00:04:46,060
Now, this takes a configuration object itself
98
00:04:46,060 --> 00:04:51,060
and here, we now can configure a couple of things.
99
00:04:51,790 --> 00:04:55,080
For example, we can set the credentials key
100
00:04:55,080 --> 00:04:58,050
and then here define what our credentials are.
101
00:04:58,050 --> 00:04:59,620
Email and password.
102
00:04:59,620 --> 00:05:03,420
We could use that to let NextAuth generate a login
103
00:05:03,420 --> 00:05:05,650
form for us.
104
00:05:05,650 --> 00:05:08,980
Here, however, I don't wanna let NextAuth generate
105
00:05:08,980 --> 00:05:10,380
a form for me.
106
00:05:10,380 --> 00:05:12,210
I already have one
107
00:05:12,210 --> 00:05:14,700
and hence, I'll not set credentials.
108
00:05:14,700 --> 00:05:18,190
The only thing we need to set here actually is authorize
109
00:05:18,190 --> 00:05:21,730
and authorize turns out to be a method.
110
00:05:21,730 --> 00:05:25,380
It's a method which Next.js will call for us
111
00:05:25,380 --> 00:05:29,850
when it receives a incoming login request.
112
00:05:29,850 --> 00:05:32,280
At the moment, we're not sending such requests yet
113
00:05:32,280 --> 00:05:34,460
but we will soon do so.
114
00:05:34,460 --> 00:05:36,470
Authorize is an async function,
115
00:05:36,470 --> 00:05:38,310
so it returns a promise,
116
00:05:38,310 --> 00:05:41,240
and as a argument, we get the credentials
117
00:05:41,240 --> 00:05:42,870
that were submitted.
118
00:05:42,870 --> 00:05:45,440
And that is the object with the data we submitted,
119
00:05:45,440 --> 00:05:47,580
for example, email, password.
120
00:05:47,580 --> 00:05:52,580
In here, we now have to bring our own authorization logic,
121
00:05:52,590 --> 00:05:55,150
check if the credentials are valid
122
00:05:55,150 --> 00:05:58,160
and tell the user if that's not the case.
123
00:05:58,160 --> 00:06:00,843
For example, throw an error if that's not the case.
124
00:06:01,740 --> 00:06:06,680
Therefore, in here we again wanna connect to the database
125
00:06:06,680 --> 00:06:08,930
and hence, import connectToDatabase
126
00:06:08,930 --> 00:06:10,233
from the lib folder.
127
00:06:11,280 --> 00:06:14,300
And get hold of that client here
128
00:06:14,300 --> 00:06:15,623
by awaiting this.
129
00:06:16,830 --> 00:06:19,840
We also wanna close the client later, of course.
130
00:06:19,840 --> 00:06:21,410
So let's already do that
131
00:06:21,410 --> 00:06:23,160
so that we don't forget it.
132
00:06:23,160 --> 00:06:25,950
And then we wanna find out if we have a user
133
00:06:25,950 --> 00:06:27,570
for the entered email
134
00:06:27,570 --> 00:06:31,540
and if we have a user with that password then.
135
00:06:31,540 --> 00:06:33,223
So if that password is correct.
136
00:06:34,220 --> 00:06:37,430
Hence, let's first of all check if we have a user.
137
00:06:37,430 --> 00:06:41,160
For that, I'll have my usersCollection,
138
00:06:41,160 --> 00:06:46,160
which I get access to with client.db.collection users.
139
00:06:46,610 --> 00:06:48,050
Let's do that in one go.
140
00:06:48,050 --> 00:06:50,523
And then we can use the usersCollection
141
00:06:51,500 --> 00:06:54,416
to find one user where the email
142
00:06:54,416 --> 00:06:58,700
is equal to credentials.email and I'm expecting
143
00:06:58,700 --> 00:07:02,080
that credentials will have a email property.
144
00:07:02,080 --> 00:07:03,510
I can expect this
145
00:07:03,510 --> 00:07:07,400
because it will be us who later set those credentials
146
00:07:07,400 --> 00:07:11,040
when we send a request from the client-side code.
147
00:07:11,040 --> 00:07:13,120
So I expect to have a email field
148
00:07:13,120 --> 00:07:15,040
in the credentials object
149
00:07:15,040 --> 00:07:18,720
and then I check if I find a user with that email.
150
00:07:18,720 --> 00:07:19,680
We should await this
151
00:07:19,680 --> 00:07:22,503
because it's an asynchronous task.
152
00:07:24,080 --> 00:07:25,400
Returning a promise
153
00:07:25,400 --> 00:07:27,913
and then here we got our user.
154
00:07:29,500 --> 00:07:33,280
Now, if we don't find a user, if not user,
155
00:07:33,280 --> 00:07:36,580
then we know that there is no user with that email address.
156
00:07:36,580 --> 00:07:40,210
In that case, we can throw a new Error
157
00:07:40,210 --> 00:07:44,753
where we say No user found, or anything like that.
158
00:07:45,600 --> 00:07:49,190
Now, when you throw an error inside of authorize,
159
00:07:49,190 --> 00:07:51,700
authorize will reject that promise,
160
00:07:51,700 --> 00:07:53,110
which it generates
161
00:07:53,110 --> 00:07:57,020
and it will then by default redirect the client
162
00:07:57,020 --> 00:07:58,300
to another page.
163
00:07:58,300 --> 00:08:00,220
But we will be able to override this
164
00:08:00,220 --> 00:08:02,570
so that we stay on this login page
165
00:08:02,570 --> 00:08:05,420
and maybe just show an error there.
166
00:08:05,420 --> 00:08:07,210
But that's something we'll do later.
167
00:08:07,210 --> 00:08:08,623
So here we throw an error.
168
00:08:09,460 --> 00:08:11,300
But if we make it past this if check,
169
00:08:11,300 --> 00:08:15,040
we know that we found a user for the email address.
170
00:08:15,040 --> 00:08:17,060
That's nice but we now also need
171
00:08:17,060 --> 00:08:19,453
to find out whether the password is correct.
172
00:08:20,360 --> 00:08:23,150
Now, keep in mind that we hashed the password,
173
00:08:23,150 --> 00:08:24,870
so we will not be able
174
00:08:24,870 --> 00:08:27,850
to just compare the submitted password
175
00:08:27,850 --> 00:08:29,530
with the stored password.
176
00:08:29,530 --> 00:08:32,030
The stored password will never be equal
177
00:08:32,030 --> 00:08:33,303
because it's hashed.
178
00:08:34,330 --> 00:08:36,740
Now, we can't unhash the password
179
00:08:36,740 --> 00:08:39,990
but we can hash the incoming password again
180
00:08:39,990 --> 00:08:41,640
to find out if it's equal.
181
00:08:41,640 --> 00:08:44,190
But if we just call hashPassword again,
182
00:08:44,190 --> 00:08:46,610
we would also generate a different hash
183
00:08:46,610 --> 00:08:49,270
because it's not always the same.
184
00:08:49,270 --> 00:08:52,640
But bcrypt.js has a method that helps us.
185
00:08:52,640 --> 00:08:55,220
It has the compare function.
186
00:08:55,220 --> 00:08:59,040
And that allows us to find out if a plaintext password
187
00:08:59,040 --> 00:09:01,380
matches a hashedPassword.
188
00:09:01,380 --> 00:09:04,900
So if that plaintext password could result
189
00:09:04,900 --> 00:09:07,250
in the same hashedPassword
190
00:09:07,250 --> 00:09:08,440
and if that's the case,
191
00:09:08,440 --> 00:09:11,650
we know that the passwords are equal.
192
00:09:11,650 --> 00:09:15,020
For this we here export another async function.
193
00:09:15,020 --> 00:09:19,580
verifyPassword could be the function name
194
00:09:19,580 --> 00:09:22,280
and here we then get the plaintext password
195
00:09:22,280 --> 00:09:24,043
and the hashedPassword,
196
00:09:25,610 --> 00:09:27,490
so both passwords.
197
00:09:27,490 --> 00:09:29,960
And then we run compare
198
00:09:29,960 --> 00:09:32,570
and there we pass in the plaintext password
199
00:09:32,570 --> 00:09:34,607
and the hashedPassword.
200
00:09:36,370 --> 00:09:39,893
And await this because compare does return a promise.
201
00:09:40,930 --> 00:09:42,360
And that will return a Boolean,
202
00:09:42,360 --> 00:09:44,840
which is true if the passwords are equal
203
00:09:44,840 --> 00:09:46,300
and false otherwise
204
00:09:46,300 --> 00:09:49,763
and hence here I'll return that Boolean.
205
00:09:50,850 --> 00:09:53,913
Then back in our authorize function,
206
00:09:56,211 --> 00:09:57,720
we can run verifyPassword
207
00:09:58,870 --> 00:10:01,190
and pass in credentials.password,
208
00:10:01,190 --> 00:10:03,090
which is the submitted password
209
00:10:03,090 --> 00:10:06,030
with which the user tries to log in.
210
00:10:06,030 --> 00:10:07,820
And as a second argument,
211
00:10:07,820 --> 00:10:09,920
the password's stores in the database
212
00:10:09,920 --> 00:10:11,660
so in that user object.
213
00:10:11,660 --> 00:10:16,660
So we pass in user.password
214
00:10:16,940 --> 00:10:18,110
as a second argument,
215
00:10:18,110 --> 00:10:19,980
accessing that password field,
216
00:10:19,980 --> 00:10:21,483
which is stored in MongoDB.
217
00:10:22,640 --> 00:10:23,980
We need to await this
218
00:10:23,980 --> 00:10:28,050
because verifyPassword is a async function
219
00:10:28,050 --> 00:10:30,420
and hence returns a promise.
220
00:10:30,420 --> 00:10:33,333
And then we got our isValid result here.
221
00:10:34,240 --> 00:10:36,100
Now, if this is not valid,
222
00:10:36,100 --> 00:10:38,130
if the password is not valid,
223
00:10:38,130 --> 00:10:40,900
then again, we wanna throw an error.
224
00:10:40,900 --> 00:10:45,310
We could say Could not log you in.
225
00:10:45,310 --> 00:10:46,353
Something like this.
226
00:10:47,330 --> 00:10:49,890
If we make it past this if check as well,
227
00:10:49,890 --> 00:10:53,480
we know that we have a user for the given email address
228
00:10:53,480 --> 00:10:55,790
and that the password is valid.
229
00:10:55,790 --> 00:10:57,010
So in that case,
230
00:10:57,010 --> 00:10:59,720
the user is logged in and in that case,
231
00:10:59,720 --> 00:11:02,530
here we should return an object.
232
00:11:02,530 --> 00:11:05,610
If we return an object inside of authorize,
233
00:11:05,610 --> 00:11:10,370
we let nextAuth know that authorization succeeded
234
00:11:10,370 --> 00:11:12,840
so that the user is logged in.
235
00:11:12,840 --> 00:11:16,370
And this object will then actually be encoded
236
00:11:16,370 --> 00:11:18,920
into that JSON Web Token.
237
00:11:18,920 --> 00:11:20,410
Hence here, we could, for example,
238
00:11:20,410 --> 00:11:22,720
include the user email.
239
00:11:22,720 --> 00:11:25,830
We should not pass the entire user object
240
00:11:25,830 --> 00:11:28,320
because we don't wanna include the password.
241
00:11:28,320 --> 00:11:31,290
Even though it's hashed, we don't wanna expose that
242
00:11:31,290 --> 00:11:33,030
to the client.
243
00:11:33,030 --> 00:11:34,870
So that's the object we return
244
00:11:34,870 --> 00:11:38,910
and that will then be encoded in a JSON Web Token.
245
00:11:38,910 --> 00:11:40,390
But speaking of that,
246
00:11:40,390 --> 00:11:44,040
to make sure that a JSON Web Token is created,
247
00:11:44,040 --> 00:11:47,920
we should go to the NextAuth config object
248
00:11:47,920 --> 00:11:50,640
and besides setting up our providers,
249
00:11:50,640 --> 00:11:55,640
also add the sessions option here.
250
00:11:55,980 --> 00:11:58,873
That's another option which you can set up here.
251
00:12:00,510 --> 00:12:03,093
Actually, it's session, not sessions.
252
00:12:04,570 --> 00:12:06,340
It's a object where you can configure
253
00:12:06,340 --> 00:12:10,610
how that session for an authenticated user will be managed
254
00:12:10,610 --> 00:12:13,430
and there, you've got a jwt key,
255
00:12:13,430 --> 00:12:15,200
which should be set to true
256
00:12:15,200 --> 00:12:18,340
so that JSON Web Tokens are being used.
257
00:12:18,340 --> 00:12:21,080
For some other authentication providers,
258
00:12:21,080 --> 00:12:23,620
you have other ways of managing this.
259
00:12:23,620 --> 00:12:26,960
For example, that a session is stored in a database
260
00:12:26,960 --> 00:12:30,070
but for credential-based authentication,
261
00:12:30,070 --> 00:12:34,110
for this provider, you must use JWT
262
00:12:34,110 --> 00:12:35,960
and set this to true.
263
00:12:35,960 --> 00:12:38,570
As you see, it I would be set to true automatically
264
00:12:38,570 --> 00:12:40,770
if you don't specify a database
265
00:12:40,770 --> 00:12:43,180
and we aren't specifying a database
266
00:12:43,180 --> 00:12:47,200
because we handle all database access manually anyways
267
00:12:47,200 --> 00:12:49,250
with this specific provider
268
00:12:49,250 --> 00:12:50,810
but nonetheless, setting it
269
00:12:50,810 --> 00:12:53,483
to true explicitly also isn't too bad.
270
00:12:54,410 --> 00:12:56,970
Now, if you do use other providers,
271
00:12:56,970 --> 00:12:58,150
then you might, of course,
272
00:12:58,150 --> 00:13:01,340
we able to add a database and user session.
273
00:13:01,340 --> 00:13:06,060
It really depends on which authentication provider you use.
274
00:13:06,060 --> 00:13:09,750
For example, if you use the email authentication provider
275
00:13:09,750 --> 00:13:13,580
where you get an email with the magic link sent to you,
276
00:13:13,580 --> 00:13:15,640
then you need to add a database
277
00:13:15,640 --> 00:13:17,500
in which the emails will be stored
278
00:13:17,500 --> 00:13:19,733
and you don't need to use JWT.
279
00:13:20,620 --> 00:13:21,860
But that's just a side note.
280
00:13:21,860 --> 00:13:23,750
Here we are using JWT.
281
00:13:23,750 --> 00:13:26,440
We are using credentials and hence we need
282
00:13:26,440 --> 00:13:28,850
to configure it like this.
283
00:13:28,850 --> 00:13:31,860
Now, before using this API route though,
284
00:13:31,860 --> 00:13:33,480
before sending requests,
285
00:13:33,480 --> 00:13:34,870
there's one thing I wanna do.
286
00:13:34,870 --> 00:13:36,700
Client.close, of course, should be called
287
00:13:36,700 --> 00:13:38,200
before we return
288
00:13:38,200 --> 00:13:40,850
and also should be called if we throw an error
289
00:13:40,850 --> 00:13:43,750
so that we still close that database connection.
290
00:13:43,750 --> 00:13:46,260
That is something we should do here.
291
00:13:46,260 --> 00:13:49,480
And actually I just saw, this should be hashedPassword,
292
00:13:49,480 --> 00:13:51,300
of course, not hashPassword.
293
00:13:51,300 --> 00:13:53,260
So that's one thing.
294
00:13:53,260 --> 00:13:55,240
That's now the backend.
295
00:13:55,240 --> 00:13:59,333
That's the authentication API route using NextAuth.
296
00:14:00,290 --> 00:14:03,750
Let's now find out what we do on the front end
297
00:14:03,750 --> 00:14:06,313
on the client to log users in.
22404
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.