1
00:00:02,140 --> 00:00:04,650
Now we learned a lot about authentication,

2
00:00:04,650 --> 00:00:07,560
sessions, cookies, and so on.

3
00:00:07,560 --> 00:00:10,030
I will conclude this core section

4
00:00:10,030 --> 00:00:12,410
and the new knowledge I want to pass on to you

5
00:00:12,410 --> 00:00:13,830
for this section

6
00:00:13,830 --> 00:00:16,160
by having a look at authentication

7
00:00:16,160 --> 00:00:18,870
versus authorization.

8
00:00:18,870 --> 00:00:21,380
Two terms that are kind of related,

9
00:00:21,380 --> 00:00:24,290
but describe different things.

10
00:00:24,290 --> 00:00:25,710
In this course section,

11
00:00:25,710 --> 00:00:29,330
we thus far focused on authentication.

12
00:00:29,330 --> 00:00:33,210
Now authorization is related, but different.

13
00:00:33,210 --> 00:00:36,610
With authentication, we're talking about signing up

14
00:00:36,610 --> 00:00:38,720
and logging in with credentials

15
00:00:38,720 --> 00:00:41,010
and about storing data in a session

16
00:00:41,010 --> 00:00:42,840
to grant a user access

17
00:00:42,840 --> 00:00:46,510
to restricted resources and pages.

18
00:00:46,510 --> 00:00:50,610
With authorization, we take this a step further.

19
00:00:50,610 --> 00:00:54,320
As a user you might be logged in and authenticated,

20
00:00:54,320 --> 00:00:56,250
and you still might not be allowed

21
00:00:56,250 --> 00:00:57,990
to do everything.

22
00:00:57,990 --> 00:01:02,610
With authorization, we restrict the actions

23
00:01:02,610 --> 00:01:04,239
that can be taken by a user

24
00:01:04,239 --> 00:01:07,250
or the pages that can be visited by a user,

25
00:01:07,250 --> 00:01:10,353
even if he or she is authenticated.

26
00:01:11,400 --> 00:01:13,600
And a typical example would be

27
00:01:13,600 --> 00:01:15,870
that you have an online shop.

28
00:01:15,870 --> 00:01:17,120
And if you log in,

29
00:01:17,120 --> 00:01:19,760
you can only view your orders.

30
00:01:19,760 --> 00:01:23,140
You can't view all the orders of all the users.

31
00:01:23,140 --> 00:01:26,130
You can only see your orders.

32
00:01:26,130 --> 00:01:27,830
Or if you're building a blog,

33
00:01:27,830 --> 00:01:29,530
then you might be allowed

34
00:01:29,530 --> 00:01:31,710
to log in as an administrator,

35
00:01:31,710 --> 00:01:33,970
who is able to delete and edit

36
00:01:33,970 --> 00:01:36,000
and create blog posts.

37
00:01:36,000 --> 00:01:38,240
And maybe you also can log in

38
00:01:38,240 --> 00:01:39,830
as a regular user

39
00:01:39,830 --> 00:01:41,810
so that you can leave comments,

40
00:01:41,810 --> 00:01:43,850
but you then still are not allowed

41
00:01:43,850 --> 00:01:46,423
to edit or delete blog posts.

42
00:01:47,500 --> 00:01:49,320
So even if you are logged in,

43
00:01:49,320 --> 00:01:51,900
you typically can't do everything.

44
00:01:51,900 --> 00:01:55,440
It, of course, depends on which website you're building.

45
00:01:55,440 --> 00:01:57,930
And I want to show you how you could implement

46
00:01:57,930 --> 00:02:01,020
authorization here as well.

47
00:02:01,020 --> 00:02:05,060
To implement this, in this existing application,

48
00:02:05,060 --> 00:02:07,160
you're in this existing website,

49
00:02:07,160 --> 00:02:10,680
I will copy the admin.ejs file

50
00:02:10,680 --> 00:02:15,613
and create a new profile.ejs file based on it.

51
00:02:16,900 --> 00:02:18,570
And in this profile template,

52
00:02:18,570 --> 00:02:21,190
I'll say "The Profile Page,"

53
00:02:21,190 --> 00:02:23,020
and then just quickly replace

54
00:02:23,020 --> 00:02:24,700
all that content here

55
00:02:24,700 --> 00:02:26,510
with one paragraph there,

56
00:02:26,510 --> 00:02:28,490
where I say "Your profile."

57
00:02:28,490 --> 00:02:30,053
It's just a dummy page.

58
00:02:31,590 --> 00:02:34,723
And I'll say "Profile" here as a title.

59
00:02:36,690 --> 00:02:39,770
Now, my idea is that we have this page as well,

60
00:02:39,770 --> 00:02:42,600
and every logged in user should be allowed

61
00:02:42,600 --> 00:02:44,360
to reach this page,

62
00:02:44,360 --> 00:02:47,210
but only administrators should be allowed

63
00:02:47,210 --> 00:02:48,803
to reach the admin page.

64
00:02:50,150 --> 00:02:52,140
Therefore I'll go to the routes,

65
00:02:52,140 --> 00:02:55,550
and first of all add another route.

66
00:02:55,550 --> 00:02:58,683
I will simply copy my admin route here,

67
00:02:59,690 --> 00:03:01,180
this get route,

68
00:03:01,180 --> 00:03:04,600
and add it as a /profile route,

69
00:03:04,600 --> 00:03:07,290
where I render the profile template

70
00:03:07,290 --> 00:03:09,360
if we are authenticated.

71
00:03:09,360 --> 00:03:12,250
The check is the same as before.

72
00:03:12,250 --> 00:03:13,870
I render the 401 page

73
00:03:13,870 --> 00:03:15,580
if we are not authenticated.

74
00:03:15,580 --> 00:03:17,173
So that hasn't changed.

75
00:03:18,140 --> 00:03:21,910
And now I will also go to my header here

76
00:03:21,910 --> 00:03:25,010
and add a new list item to it,

77
00:03:25,010 --> 00:03:27,290
which links to this profile page,

78
00:03:27,290 --> 00:03:29,500
so to /profile.

79
00:03:31,480 --> 00:03:33,230
With all of that, if we reload,

80
00:03:33,230 --> 00:03:34,580
we got that page here

81
00:03:34,580 --> 00:03:36,450
and we can now visit both pages

82
00:03:36,450 --> 00:03:37,700
if we are logged in.

83
00:03:37,700 --> 00:03:39,290
And if I do log out,

84
00:03:39,290 --> 00:03:41,573
we can visit neither of these two pages.

85
00:03:42,410 --> 00:03:44,580
But now again, only an administrator

86
00:03:44,580 --> 00:03:46,713
should be allowed to access this page.

87
00:03:47,720 --> 00:03:49,640
Now, to practice that,

88
00:03:49,640 --> 00:03:52,750
I will manually edit one user

89
00:03:52,750 --> 00:03:56,223
to turn him or her into an administrator.

90
00:03:57,230 --> 00:04:00,090
And I'll simply take the first user here.

91
00:04:00,090 --> 00:04:03,310
Of course, you could also edit the signup page

92
00:04:03,310 --> 00:04:05,170
so that it has a check box

93
00:04:05,170 --> 00:04:07,920
that allows you to sign up as an administrator,

94
00:04:07,920 --> 00:04:09,630
but that's also not realistic

95
00:04:09,630 --> 00:04:11,620
because you typically don't let users

96
00:04:11,620 --> 00:04:14,140
choose whether they are an administrator,

97
00:04:14,140 --> 00:04:16,420
but you would instead manually assign

98
00:04:16,420 --> 00:04:18,050
the administrator role.

99
00:04:18,050 --> 00:04:20,709
For example, through an extra interface

100
00:04:20,709 --> 00:04:22,310
or here, in this case,

101
00:04:22,310 --> 00:04:24,353
simply directly in the database.

102
00:04:25,190 --> 00:04:28,080
So for that, I'll take the ID of this user

103
00:04:28,990 --> 00:04:31,457
and then run db.users.updateOne,

104
00:04:32,756 --> 00:04:34,650
because I want to update this document.

105
00:04:34,650 --> 00:04:36,330
And for my filter condition,

106
00:04:36,330 --> 00:04:38,170
I'll look for the user

107
00:04:38,170 --> 00:04:41,393
where the ID is equal to this ObjectId I grabbed.

108
00:04:42,500 --> 00:04:44,880
And then the second parameter value here

109
00:04:44,880 --> 00:04:47,490
defines how we want to update the user,

110
00:04:47,490 --> 00:04:51,263
and there we use this special dollar sign set property,

111
00:04:52,410 --> 00:04:55,880
and then I'll set this to a new object.

112
00:04:55,880 --> 00:04:58,900
And in this new object, I'll add my new key.

113
00:04:58,900 --> 00:05:02,860
Let's say the isAdmin key.

114
00:05:02,860 --> 00:05:06,180
It's broken across two lines here.

115
00:05:06,180 --> 00:05:07,880
I'll zoom out a bit.

116
00:05:07,880 --> 00:05:09,950
So I'll set the isAdmin key here,

117
00:05:09,950 --> 00:05:11,193
and set this to true.

118
00:05:12,770 --> 00:05:16,053
Only this user receives this flag.

119
00:05:17,130 --> 00:05:19,110
If I hit Enter, this was updated.

120
00:05:19,110 --> 00:05:21,490
And if I now find all my users,

121
00:05:21,490 --> 00:05:24,600
we can see that the first user has the admin flag,

122
00:05:24,600 --> 00:05:26,253
the other user doesn't have it.

123
00:05:27,550 --> 00:05:29,450
This is also not the only way

124
00:05:29,450 --> 00:05:32,130
of implementing authorization.

125
00:05:32,130 --> 00:05:34,230
There are very elaborate ways

126
00:05:34,230 --> 00:05:36,360
where you have multiple roles

127
00:05:36,360 --> 00:05:39,020
that might be stored in a separate collection,

128
00:05:39,020 --> 00:05:41,040
and a user then might have one

129
00:05:41,040 --> 00:05:44,470
or multiple roles assigned to him or her.

130
00:05:44,470 --> 00:05:45,303
And so on.

131
00:05:45,303 --> 00:05:48,040
There are different ways of implementing authorization.

132
00:05:48,040 --> 00:05:50,210
This is a relatively simple one,

133
00:05:50,210 --> 00:05:53,420
where I simply set a specific flag,

134
00:05:53,420 --> 00:05:56,450
but it shows what authorization is all about.

135
00:05:56,450 --> 00:05:59,363
And that is what this lecture here is all about.

136
00:06:00,630 --> 00:06:02,340
So isAdmin is true here.

137
00:06:02,340 --> 00:06:06,150
That's in the end the role I'm signing with this flag.

138
00:06:06,150 --> 00:06:07,640
And now the admin page

139
00:06:07,640 --> 00:06:10,523
should only be visitable if this is true.

140
00:06:11,950 --> 00:06:14,390
Now, how do we implement authorization

141
00:06:14,390 --> 00:06:15,603
in our code then?

142
00:06:16,480 --> 00:06:19,420
Again, there are different ways of doing that.

143
00:06:19,420 --> 00:06:22,340
When we authenticate a user,

144
00:06:22,340 --> 00:06:24,050
so when we log a user in,

145
00:06:24,050 --> 00:06:26,470
then we store some user data in a session.

146
00:06:26,470 --> 00:06:28,490
For example, the ID.

147
00:06:28,490 --> 00:06:31,610
Here we could also store the information

148
00:06:31,610 --> 00:06:34,110
whether the user is an admin or not,

149
00:06:34,110 --> 00:06:37,423
by simply reaching out to existingUser.isAdmin.

150
00:06:38,480 --> 00:06:41,980
And this is either undefined if it wasn't set,

151
00:06:41,980 --> 00:06:46,130
in which case isAdmin will have undefined as a value,

152
00:06:46,130 --> 00:06:48,230
or if a user has this flag,

153
00:06:48,230 --> 00:06:50,930
the flag value is used.

154
00:06:50,930 --> 00:06:52,290
So that would allow us to store

155
00:06:52,290 --> 00:06:54,370
the isAdmin value in a session,

156
00:06:54,370 --> 00:06:56,240
and that would be absolutely fine

157
00:06:56,240 --> 00:06:58,283
in a good way of implementing this.

158
00:06:59,720 --> 00:07:02,300
Alternatively, of course, we don't store it.

159
00:07:02,300 --> 00:07:05,170
We just store the ID and maybe the email.

160
00:07:05,170 --> 00:07:08,970
And we instead fetch the user record based on that ID

161
00:07:08,970 --> 00:07:11,250
in the place where we want to check

162
00:07:11,250 --> 00:07:14,043
whether that user is an administrator or not.

163
00:07:15,190 --> 00:07:18,250
That will require an extra database query,

164
00:07:18,250 --> 00:07:20,670
but it keeps the session a bit leaner.

165
00:07:20,670 --> 00:07:23,970
Another advantage is that if you ever change

166
00:07:23,970 --> 00:07:26,340
the admin status of a user,

167
00:07:26,340 --> 00:07:28,680
you don't have to update the session,

168
00:07:28,680 --> 00:07:30,470
which you would have to do if you store it

169
00:07:30,470 --> 00:07:32,410
in the session as well.

170
00:07:32,410 --> 00:07:34,770
If you only store it in the user document,

171
00:07:34,770 --> 00:07:37,480
the session does not need to be updated

172
00:07:37,480 --> 00:07:40,110
if you change that data.

173
00:07:40,110 --> 00:07:41,900
And that's, in general, true.

174
00:07:41,900 --> 00:07:44,690
The more user data you store in a session,

175
00:07:44,690 --> 00:07:47,480
the more data needs to be updated in a session

176
00:07:47,480 --> 00:07:49,920
if that user data changes.

177
00:07:49,920 --> 00:07:51,400
You should also keep that in mind

178
00:07:51,400 --> 00:07:53,050
when storing the email.

179
00:07:53,050 --> 00:07:55,660
If a user then gets a new email address,

180
00:07:55,660 --> 00:07:58,090
you'll have to update it in the session as well,

181
00:07:58,090 --> 00:08:01,480
at least if you rely on that email in the session

182
00:08:01,480 --> 00:08:03,363
anywhere else in your website.

183
00:08:04,490 --> 00:08:06,490
So therefore here I'll not store the role

184
00:08:06,490 --> 00:08:07,640
in the session,

185
00:08:07,640 --> 00:08:09,180
but instead I'll just get it

186
00:08:09,180 --> 00:08:10,970
just in time when I need it.

187
00:08:10,970 --> 00:08:13,363
And that's here in this get admin route.

188
00:08:14,580 --> 00:08:16,900
The first step still is to check

189
00:08:16,900 --> 00:08:19,020
whether a user is authenticated,

190
00:08:19,020 --> 00:08:21,260
because if a user is not authenticated,

191
00:08:21,260 --> 00:08:24,020
he or she also can't be authorized

192
00:08:24,020 --> 00:08:25,610
to access this page.

193
00:08:25,610 --> 00:08:28,830
So in this case, we don't even have to continue.

194
00:08:28,830 --> 00:08:31,190
But if we make it past this first if-check,

195
00:08:31,190 --> 00:08:33,190
we know the user is authenticated,

196
00:08:33,190 --> 00:08:36,130
and then I want to check if it's the right kind of user,

197
00:08:36,130 --> 00:08:37,263
if it's an admin.

198
00:08:38,280 --> 00:08:41,360
So then here I'll get my user

199
00:08:41,360 --> 00:08:45,630
by using the database getDb,

200
00:08:45,630 --> 00:08:47,253
and there the users collection.

201
00:08:48,430 --> 00:08:51,320
And I'll find the user by ID, let's say,

202
00:08:51,320 --> 00:08:53,330
by looking for ID, _id,

203
00:08:54,180 --> 00:08:57,323
being equal to request.session.user.id.

204
00:08:59,180 --> 00:09:02,800
Keep in mind that in my user session object,

205
00:09:02,800 --> 00:09:06,363
I have this ID key, which is the user's ID.

206
00:09:08,800 --> 00:09:11,180
Now that is an asynchronous operation,

207
00:09:11,180 --> 00:09:14,600
so I will convert this into a async function

208
00:09:14,600 --> 00:09:17,040
so that we can use the await keyword here

209
00:09:17,040 --> 00:09:19,400
and wait for this result.

210
00:09:19,400 --> 00:09:22,483
And then we should find a user for this given ID.

211
00:09:23,810 --> 00:09:26,290
Now, if we don't find the user

212
00:09:26,290 --> 00:09:27,610
for whatever reason,

213
00:09:27,610 --> 00:09:29,170
though that shouldn't happen,

214
00:09:29,170 --> 00:09:30,900
or more importantly,

215
00:09:30,900 --> 00:09:33,910
if the user is not an admin,

216
00:09:33,910 --> 00:09:36,150
so if isAdmin is false,

217
00:09:36,150 --> 00:09:37,850
which is what I check here,

218
00:09:37,850 --> 00:09:41,480
then I don't want to render the admin template.

219
00:09:41,480 --> 00:09:44,290
Instead then I want to render a new template,

220
00:09:44,290 --> 00:09:46,063
which I'll name 403.

221
00:09:47,240 --> 00:09:49,450
This is a template that doesn't exist yet,

222
00:09:49,450 --> 00:09:52,090
but I'll copy the 401 template

223
00:09:52,090 --> 00:09:53,883
and rename it to 403.

224
00:09:54,810 --> 00:09:58,170
And in there I'll say "Not authorized.

225
00:10:00,077 --> 00:10:02,687
"You are not authorized

226
00:10:02,687 --> 00:10:04,880
"and therefore not allowed to access this page."

227
00:10:04,880 --> 00:10:06,220
And that's different.

228
00:10:06,220 --> 00:10:07,490
You are authenticated,

229
00:10:07,490 --> 00:10:09,900
but you are still not allowed to access this page.

230
00:10:09,900 --> 00:10:11,393
That's what I'm saying here.

231
00:10:13,810 --> 00:10:15,640
And I don't just render it like this.

232
00:10:15,640 --> 00:10:19,010
Instead I will also set the status code here

233
00:10:19,010 --> 00:10:22,500
to 403 because that is the status code

234
00:10:22,500 --> 00:10:23,500
that you should use

235
00:10:23,500 --> 00:10:25,160
if a user is authenticated,

236
00:10:25,160 --> 00:10:27,670
but not authorized to do something

237
00:10:27,670 --> 00:10:28,723
or to see something.

238
00:10:36,673 --> 00:10:39,310
And with that, if we save this,

239
00:10:39,310 --> 00:10:41,120
if I log out,

240
00:10:41,120 --> 00:10:43,713
if I create another new user here,

241
00:10:45,270 --> 00:10:48,093
just so that I have a non-admin user as well.

242
00:10:53,900 --> 00:10:58,023
And then if I log in with this user here,

243
00:10:59,990 --> 00:11:01,453
then you see I got not authorized

244
00:11:01,453 --> 00:11:03,870
when visiting the admin page.

245
00:11:03,870 --> 00:11:05,970
I can visit profile,

246
00:11:05,970 --> 00:11:06,803
that works,

247
00:11:06,803 --> 00:11:08,650
but I got not authorized

248
00:11:08,650 --> 00:11:11,230
when visiting the admin page.

249
00:11:11,230 --> 00:11:13,870
And therefore here, in the login route,

250
00:11:13,870 --> 00:11:15,560
in the login post route,

251
00:11:15,560 --> 00:11:18,780
we probably shouldn't redirect to /admin,

252
00:11:18,780 --> 00:11:20,630
but to /profile

253
00:11:20,630 --> 00:11:22,980
because not every user who logged in

254
00:11:22,980 --> 00:11:27,980
will be able to actually view this admin page.

255
00:11:29,090 --> 00:11:30,820
For example, this user I just showed you

256
00:11:30,820 --> 00:11:32,183
won't be able to do so.

257
00:11:33,350 --> 00:11:35,650
Now if I log out with this user,

258
00:11:35,650 --> 00:11:38,133
and I then log in with my first user,

259
00:11:40,430 --> 00:11:42,560
who is an administrator,

260
00:11:42,560 --> 00:11:45,170
then the profile page, of course, works,

261
00:11:45,170 --> 00:11:48,080
but the admin page now also works.

262
00:11:48,080 --> 00:11:51,760
Now I don't get the "Not authorized" error there,

263
00:11:51,760 --> 00:11:56,063
simply because this user now is an administrator.

264
00:11:57,020 --> 00:12:00,400
And that's how we can implement authorization as well,

265
00:12:00,400 --> 00:12:02,350
simply by adding some extra logic

266
00:12:02,350 --> 00:12:05,070
from our side to check for more

267
00:12:05,070 --> 00:12:08,420
than just the isAuthenticated flag.

268
00:12:08,420 --> 00:12:11,333
In this case, I'm also checking for the isAdmin flag.

