1
00:00:02,000 --> 00:00:03,000
So let's now get started

2
00:00:03,000 --> 00:00:05,000
with adding our own logic,

3
00:00:05,000 --> 00:00:08,000
because as I said NextAuth won't do everything for us here.

4
00:00:08,000 --> 00:00:12,000
When we roll with our own authentication system

5
00:00:12,000 --> 00:00:13,000
with our own user accounts

6
00:00:13,000 --> 00:00:18,000
and thereafter before we use NextAuth for anything,

7
00:00:18,000 --> 00:00:19,000
we will first of all,

8
00:00:19,000 --> 00:00:22,000
have to add the logic to create users

9
00:00:22,000 --> 00:00:23,000
because NextAuth can then

10
00:00:23,000 --> 00:00:26,000
help us with authenticating those users

11
00:00:26,000 --> 00:00:29,000
and with getting the token for those users,

12
00:00:29,000 --> 00:00:31,000
but to create the users themselves,

13
00:00:31,000 --> 00:00:33,000
we need to bring our own logic.

14
00:00:33,000 --> 00:00:36,000
Hence I'll bring up my dev server again,

15
00:00:36,000 --> 00:00:38,000
and I want to add an API route,

16
00:00:38,000 --> 00:00:41,000
which gets input,

17
00:00:41,000 --> 00:00:44,000
which gets a request with an email and a password,

18
00:00:44,000 --> 00:00:47,000
which in the end should be sent from the log in page,

19
00:00:47,000 --> 00:00:50,000
if we are creating a new account

20
00:00:50,000 --> 00:00:53,000
and then that data should be used to store that user,

21
00:00:53,000 --> 00:00:57,000
and I will use MongoDB again as a database

22
00:00:57,000 --> 00:00:59,000
for storing the user data,

23
00:00:59,000 --> 00:01:02,000
but you can go with any database you want.

24
00:01:02,000 --> 00:01:04,000
It doesn't have to be MongoDB,

25
00:01:04,000 --> 00:01:06,000
but MongoDB

26
00:01:06,000 --> 00:01:08,000
especially when using MongoDB Atlas

27
00:01:08,000 --> 00:01:09,000
is just great to use,

28
00:01:09,000 --> 00:01:11,000
free to get started,

29
00:01:11,000 --> 00:01:13,000
easy to use with Javascript

30
00:01:13,000 --> 00:01:15,000
and already hosted for us,

31
00:01:15,000 --> 00:01:16,000
so that's great.

32
00:01:16,000 --> 00:01:18,000
Hence we'll need to add an API route

33
00:01:18,000 --> 00:01:21,000
and therefore this API folder in the pages folder,

34
00:01:21,000 --> 00:01:26,000
and in that API folder, I'll then add an auth subfolder,

35
00:01:26,000 --> 00:01:28,000
and in that auth subfolder,

36
00:01:29,000 --> 00:01:30,000
a sign up JS file.

37
00:01:30,000 --> 00:01:32,000
Now the file name is up to you,

38
00:01:32,000 --> 00:01:36,000
and in there I'll then define my handler function

39
00:01:36,000 --> 00:01:40,000
which will be responsible for creating a new user,

40
00:01:40,000 --> 00:01:41,000
and we should of course,

41
00:01:41,000 --> 00:01:43,000
as always export that function thereafter.

42
00:01:44,000 --> 00:01:47,000
Now in here, we want to connect

43
00:01:47,000 --> 00:01:51,000
to the database and store the incoming user data.

44
00:01:51,000 --> 00:01:54,000
Hence I will actually quit the dev server one more time

45
00:01:54,000 --> 00:01:58,000
and then install the MongoDB package again

46
00:01:58,000 --> 00:02:01,000
as we also did before in the course already

47
00:02:01,000 --> 00:02:03,000
and then restart the dev server

48
00:02:03,000 --> 00:02:05,000
because we'll need that MongoDB package

49
00:02:05,000 --> 00:02:08,000
to successfully connect to that database

50
00:02:08,000 --> 00:02:10,000
and talk to that database.

51
00:02:11,000 --> 00:02:14,000
We will actually also talk to that database

52
00:02:14,000 --> 00:02:18,000
from multiple functions here

53
00:02:18,000 --> 00:02:20,000
from multiple API routes later

54
00:02:20,000 --> 00:02:22,000
and therefore to share some logic,

55
00:02:22,000 --> 00:02:27,000
I'll add a new folder on my route level of the project,

56
00:02:27,000 --> 00:02:29,000
a lib folder,

57
00:02:29,000 --> 00:02:32,000
we could also name it, helpers, whatever you want,

58
00:02:32,000 --> 00:02:37,000
and in there I'll add my DB JS file,

59
00:02:37,000 --> 00:02:38,000
file name of course is up to you

60
00:02:38,000 --> 00:02:41,000
and it's that file, which should help me

61
00:02:41,000 --> 00:02:44,000
with establishing a connection and so on.

62
00:02:45,000 --> 00:02:47,000
So here in this DB JS file,

63
00:02:47,000 --> 00:02:50,000
I'll import from MongoDB,

64
00:02:50,000 --> 00:02:51,000
and as before in the course,

65
00:02:51,000 --> 00:02:55,000
I'll import Mongo client

66
00:02:55,000 --> 00:02:56,000
because that's the thing

67
00:02:56,000 --> 00:02:58,000
that helps us establish a connection,

68
00:03:00,000 --> 00:03:01,000
and then I'll add a function,

69
00:03:01,000 --> 00:03:06,000
connecTtoDatabase, could be the function name

70
00:03:07,000 --> 00:03:09,000
and in there we'll do what the name implies.

71
00:03:09,000 --> 00:03:12,000
We'll use Mongo client to call the connect method,

72
00:03:12,000 --> 00:03:15,000
and then here pass our connection string

73
00:03:15,000 --> 00:03:18,000
with which we connect to a database.

74
00:03:18,000 --> 00:03:21,000
Now for MongoDB, we can get that string from

75
00:03:21,000 --> 00:03:24,000
MongoDB Atlas with a created cluster,

76
00:03:24,000 --> 00:03:26,000
and therefore you should make sure

77
00:03:26,000 --> 00:03:27,000
that you have that cluster.

78
00:03:27,000 --> 00:03:30,000
We did create that early in the course already,

79
00:03:30,000 --> 00:03:33,000
so make sure that you don't skip those previous parts

80
00:03:33,000 --> 00:03:36,000
where we talk to MongoDB already,

81
00:03:36,000 --> 00:03:38,000
and once you've got a cluster created,

82
00:03:38,000 --> 00:03:40,000
you can click on connect on your cluster,

83
00:03:40,000 --> 00:03:42,000
connect your application,

84
00:03:42,000 --> 00:03:44,000
and then it's this connection string

85
00:03:44,000 --> 00:03:48,000
which we need and which we are interested in.

86
00:03:48,000 --> 00:03:50,000
So I'll use that connection string,

87
00:03:50,000 --> 00:03:53,000
and here we now need to replace

88
00:03:53,000 --> 00:03:56,000
some pieces of data like the username, password

89
00:03:56,000 --> 00:04:00,000
and the database here.

90
00:04:00,000 --> 00:04:02,000
Now for username and password,

91
00:04:02,000 --> 00:04:04,000
I will go to database access

92
00:04:04,000 --> 00:04:06,000
and make sure that I have a valid password

93
00:04:06,000 --> 00:04:08,000
for this user here,

94
00:04:09,000 --> 00:04:11,000
create a new password and update it,

95
00:04:11,000 --> 00:04:13,000
and then use my username.

96
00:04:13,000 --> 00:04:17,000
You need at least one user with read and write access

97
00:04:17,000 --> 00:04:20,000
created in MongoDB Atlas

98
00:04:20,000 --> 00:04:22,000
and then add the password here,

99
00:04:24,000 --> 00:04:26,000
and then for the database name,

100
00:04:26,000 --> 00:04:28,000
I'll name this auth-demo,

101
00:04:28,000 --> 00:04:30,000
but that database name is up to you.

102
00:04:31,000 --> 00:04:33,000
That's now the connection string.

103
00:04:33,000 --> 00:04:36,000
Now connect returns a promise and to use async await,

104
00:04:36,000 --> 00:04:39,000
I'll add async in front of the function

105
00:04:39,000 --> 00:04:42,000
and then await this a connection result here

106
00:04:42,000 --> 00:04:45,000
or to be precise to connect the client

107
00:04:45,000 --> 00:04:47,000
which we get back as a response.

108
00:04:48,000 --> 00:04:51,000
Now this could be failing but for the moment,

109
00:04:51,000 --> 00:04:52,000
let's ignore that,

110
00:04:52,000 --> 00:04:56,000
and let's then just return that client here maybe,

111
00:04:56,000 --> 00:04:58,000
so that when someone calls connectToDatabase,

112
00:04:59,000 --> 00:05:02,000
that someone gets this client.

113
00:05:03,000 --> 00:05:07,000
Now that function should be usable from outside this file.

114
00:05:07,000 --> 00:05:09,000
So we'll export it,

115
00:05:09,000 --> 00:05:12,000
and now back in the sign up JS API route here,

116
00:05:12,000 --> 00:05:15,000
I first of all want to call connectToDatabase

117
00:05:15,000 --> 00:05:20,000
and hence import this from that lib folder and the DB file.

118
00:05:20,000 --> 00:05:23,000
Now I'll also turn this into an async function

119
00:05:23,000 --> 00:05:25,000
to use await here,

120
00:05:25,000 --> 00:05:28,000
and then here we get that connected client

121
00:05:28,000 --> 00:05:31,000
and we can then get access to the complete database

122
00:05:31,000 --> 00:05:35,000
by calling client.db() like this,

123
00:05:35,000 --> 00:05:37,000
and now that we've got access to the database,

124
00:05:37,000 --> 00:05:40,000
we want to create a new user

125
00:05:40,000 --> 00:05:43,000
and store it in some collection of that database,

126
00:05:43,000 --> 00:05:46,000
because as you learned before in this course already,

127
00:05:46,000 --> 00:05:49,000
MongoDB works with collections,

128
00:05:49,000 --> 00:05:50,000
collections of documents,

129
00:05:50,000 --> 00:05:53,000
where a single user would be a document

130
00:05:53,000 --> 00:05:58,000
and all the users would be stored together in a collection.

131
00:05:58,000 --> 00:05:59,000
We get access to a collection

132
00:05:59,000 --> 00:06:03,000
by calling the collection method on DB

133
00:06:03,000 --> 00:06:05,000
and we can use any collection we want.

134
00:06:05,000 --> 00:06:09,000
If it's doesn't exist yet, it will be created on the fly.

135
00:06:09,000 --> 00:06:13,000
So here we could maybe work with a users collection.

136
00:06:13,000 --> 00:06:15,000
Now to get the submitted user data

137
00:06:15,000 --> 00:06:17,000
we should accept the request

138
00:06:17,000 --> 00:06:21,000
and response objects here in our API route function.

139
00:06:21,000 --> 00:06:25,000
You'll learn that API route functions give us access

140
00:06:25,000 --> 00:06:27,000
to the incoming request

141
00:06:27,000 --> 00:06:29,000
and then all the tutors' response object

142
00:06:29,000 --> 00:06:31,000
to send back a response,

143
00:06:31,000 --> 00:06:34,000
and then we want to extract the incoming data,

144
00:06:34,000 --> 00:06:37,000
and actually we maybe want to do that first

145
00:06:37,000 --> 00:06:39,000
so that we only proceed

146
00:06:39,000 --> 00:06:42,000
as soon as we know that we have valid data.

147
00:06:43,000 --> 00:06:46,000
So here, we then basically get our data

148
00:06:46,000 --> 00:06:49,000
by accessing request body,

149
00:06:49,000 --> 00:06:51,000
and then from there we get our,

150
00:06:51,000 --> 00:06:53,000
let's say email and password,

151
00:06:53,000 --> 00:06:56,000
and these key names are up to you.

152
00:06:56,000 --> 00:06:59,000
I will extract them from the incoming request body.

153
00:06:59,000 --> 00:07:01,000
We will just have to make sure

154
00:07:01,000 --> 00:07:04,000
that later when we submit this form,

155
00:07:04,000 --> 00:07:07,000
this auth form that we actually do add

156
00:07:07,000 --> 00:07:10,000
email and password to the request

157
00:07:10,000 --> 00:07:12,000
which we sent to this API route

158
00:07:12,000 --> 00:07:14,000
when we want to create a user.

159
00:07:15,000 --> 00:07:18,000
So thereafter now we got that,

160
00:07:18,000 --> 00:07:20,000
and now we got email and password,

161
00:07:20,000 --> 00:07:23,000
we definitely also want to validate it.

162
00:07:23,000 --> 00:07:27,000
We want to check that we don't store invalid data.

163
00:07:27,000 --> 00:07:29,000
So if we don't have an email

164
00:07:29,000 --> 00:07:34,000
or let's say if not email includes an at symbol

165
00:07:34,000 --> 00:07:37,000
or if we don't have a password

166
00:07:37,000 --> 00:07:42,000
or if password trimmed for white space

167
00:07:42,000 --> 00:07:46,000
has a length that is let's say smaller than seven,

168
00:07:46,000 --> 00:07:49,000
so that we require at least seven characters

169
00:07:49,000 --> 00:07:50,000
for security reasons,

170
00:07:50,000 --> 00:07:53,000
if any of these conditions is met,

171
00:07:53,000 --> 00:07:56,000
so if we have invalid data,

172
00:07:56,000 --> 00:07:59,000
then I want to return to not continue

173
00:07:59,000 --> 00:08:00,000
with function execution

174
00:08:00,000 --> 00:08:03,000
and I'll send back a response

175
00:08:03,000 --> 00:08:06,000
with a 422 status code

176
00:08:06,000 --> 00:08:08,000
and some extra information

177
00:08:08,000 --> 00:08:12,000
like a message where I say invalid input,

178
00:08:12,000 --> 00:08:17,000
password should also be at least seven characters long,

179
00:08:19,000 --> 00:08:20,000
something like this.

180
00:08:22,000 --> 00:08:24,000
That's the response we sent back

181
00:08:24,000 --> 00:08:26,000
if we got invalid input.

182
00:08:27,000 --> 00:08:29,000
If we make it past this if check, though,

183
00:08:29,000 --> 00:08:31,000
we know that we have valid input

184
00:08:31,000 --> 00:08:36,000
and then we want to store our user data in the database.

185
00:08:36,000 --> 00:08:37,000
So in that users collection,

186
00:08:38,000 --> 00:08:41,000
hence here we want to insert a new document.

187
00:08:41,000 --> 00:08:43,000
We can do this with insert one,

188
00:08:43,000 --> 00:08:45,000
as we saw before in the course,

189
00:08:45,000 --> 00:08:48,000
and we can create that document on the fly here

190
00:08:48,000 --> 00:08:51,000
and simply add the email field

191
00:08:51,000 --> 00:08:56,000
which is that extracted email we got here,

192
00:08:56,000 --> 00:08:57,000
and then the password.

193
00:08:58,000 --> 00:09:01,000
However, regarding the password,

194
00:09:01,000 --> 00:09:06,000
there is something we have to keep in mind and take care of.

195
00:09:06,000 --> 00:09:08,000
We should not store the plain password

196
00:09:08,000 --> 00:09:11,000
like this in the database,

197
00:09:11,000 --> 00:09:14,000
because if our database ever gets compromised

198
00:09:14,000 --> 00:09:18,000
by some employee or a third party intruder,

199
00:09:18,000 --> 00:09:21,000
then all our user credentials

200
00:09:21,000 --> 00:09:24,000
would be usable just like this.

201
00:09:24,000 --> 00:09:26,000
Hence for security reasons,

202
00:09:26,000 --> 00:09:30,000
it is a best practice and strongly recommended,

203
00:09:30,000 --> 00:09:34,000
that you don't store plain passwords in the database

204
00:09:34,000 --> 00:09:36,000
but that you instead encrypt them

205
00:09:36,000 --> 00:09:39,000
such that they can't be decrypted,

206
00:09:39,000 --> 00:09:43,000
and we will still be able to verify them later, no worries,

207
00:09:43,000 --> 00:09:45,000
but we want to make sure that we store passwords

208
00:09:45,000 --> 00:09:47,000
in encrypted form

209
00:09:48,000 --> 00:09:50,000
and to encrypt passwords,

210
00:09:50,000 --> 00:09:52,000
we can install another third party package

211
00:09:52,000 --> 00:09:57,000
with npm install and that's bcryptjs, like this.

212
00:09:58,000 --> 00:10:02,000
That's a package which helps us encrypt passwords

213
00:10:02,000 --> 00:10:04,000
or encrypt any kind of data of course,

214
00:10:04,000 --> 00:10:07,000
but we'll use it for a password here,

215
00:10:07,000 --> 00:10:09,000
and hence, I'll start my dev server again,

216
00:10:09,000 --> 00:10:11,000
and now I want to encrypt my password

217
00:10:11,000 --> 00:10:13,000
and for this in the lib folder,

218
00:10:13,000 --> 00:10:16,000
I'll add another folder auth.js,

219
00:10:16,000 --> 00:10:19,000
which will hold those authentication

220
00:10:19,000 --> 00:10:22,000
related utility methods,

221
00:10:22,000 --> 00:10:26,000
and here I want to import from bcryptjs

222
00:10:27,000 --> 00:10:30,000
from that package we just installed,

223
00:10:30,000 --> 00:10:34,000
and from there, I want to import the hash function.

224
00:10:34,000 --> 00:10:39,000
Then I want to export an async function called hashPassword

225
00:10:42,000 --> 00:10:47,000
and take the original plain text password as an input,

226
00:10:47,000 --> 00:10:48,000
and then in there,

227
00:10:48,000 --> 00:10:52,000
call hash on that password,

228
00:10:52,000 --> 00:10:54,000
and the second argument then should be a number

229
00:10:54,000 --> 00:10:55,000
of salting rounds,

230
00:10:55,000 --> 00:10:59,000
which in the end will influence how strong that password is,

231
00:10:59,000 --> 00:11:04,000
and here a value of 12 is considered to be safe.

232
00:11:04,000 --> 00:11:05,000
The higher the number,

233
00:11:05,000 --> 00:11:07,000
the longer this function will take,

234
00:11:07,000 --> 00:11:09,000
the lower the number, the more insecure it is,

235
00:11:09,000 --> 00:11:13,000
so 12 should be an okay value

236
00:11:13,000 --> 00:11:15,000
and hash will then also return a promise

237
00:11:15,000 --> 00:11:18,000
which eventually gets gives us that encrypted password.

238
00:11:18,000 --> 00:11:23,000
So we can await this to have our hashed password here

239
00:11:23,000 --> 00:11:24,000
in the end,

240
00:11:24,000 --> 00:11:27,000
and then it's this hashed password

241
00:11:27,000 --> 00:11:29,000
which I return just like this.

242
00:11:29,000 --> 00:11:32,000
Now back in signup.js, we therefor now

243
00:11:32,000 --> 00:11:35,000
want to create such a hashed password

244
00:11:35,000 --> 00:11:36,000
and store data in our collection

245
00:11:36,000 --> 00:11:39,000
instead of the plain password.

246
00:11:39,000 --> 00:11:43,000
So here I get the hashed password

247
00:11:43,000 --> 00:11:48,000
by calling hashPassword and importing that function

248
00:11:48,000 --> 00:11:51,000
from the lib folder and the auth file there,

249
00:11:52,000 --> 00:11:54,000
and then to hashPassword,

250
00:11:54,000 --> 00:11:56,000
we pass our plain text password

251
00:11:57,000 --> 00:11:59,000
and then it's this hashed password,

252
00:11:59,000 --> 00:12:01,000
which we store in the document.

253
00:12:01,000 --> 00:12:02,000
So in the collection overall.

254
00:12:04,000 --> 00:12:06,000
Now insert one always returns a promise,

255
00:12:06,000 --> 00:12:08,000
so we can await this

256
00:12:08,000 --> 00:12:11,000
and this will return the result of this operation,

257
00:12:11,000 --> 00:12:13,000
which then for example gives us access

258
00:12:13,000 --> 00:12:16,000
to the automatically generated user ID.

259
00:12:16,000 --> 00:12:19,000
Now with that, we're storing a user in the database

260
00:12:19,000 --> 00:12:21,000
and now I want to send back

261
00:12:21,000 --> 00:12:24,000
a response offer, a success response

262
00:12:24,000 --> 00:12:29,000
where we say something like created user.

263
00:12:30,000 --> 00:12:32,000
Now I'll not implement error handling here,

264
00:12:32,000 --> 00:12:35,000
since I really want to focus on the core auth parts,

265
00:12:35,000 --> 00:12:39,000
and we saw error handling with MongoDB and so on,

266
00:12:39,000 --> 00:12:41,000
in action before already,

267
00:12:41,000 --> 00:12:43,000
and hence, I'll keep this lean and focused

268
00:12:43,000 --> 00:12:48,000
on the parts that are related to user creation in this case,

269
00:12:48,000 --> 00:12:51,000
and then for now we should be able to test this.

270
00:12:51,000 --> 00:12:53,000
In the next lecture,

271
00:12:53,000 --> 00:12:55,000
let's make sure that we send the request

272
00:12:55,000 --> 00:12:57,000
to this signup API route.

