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