1
00:00:01,530 --> 00:00:02,800
Hi and welcome back.

2
00:00:02,800 --> 00:00:05,993
In this video, I wanted to tell you about claims.

3
00:00:07,050 --> 00:00:11,290
Claims in flask-JWT-extended are just pieces of data

4
00:00:11,290 --> 00:00:14,990
we can choose to attach to the JWT payload.

5
00:00:14,990 --> 00:00:17,330
They are separate from the identity

6
00:00:17,330 --> 00:00:20,520
because the identity is used to identify a user.

7
00:00:20,520 --> 00:00:23,950
Claims are used to add some extra data that will

8
00:00:23,950 --> 00:00:28,540
allow us to do something when the JWT comes back to us.

9
00:00:28,540 --> 00:00:31,080
We're gonna look at a flow of claims

10
00:00:31,080 --> 00:00:33,250
so that it becomes a bit clearer.

11
00:00:33,250 --> 00:00:36,200
I'm gonna open app.py here.

12
00:00:36,200 --> 00:00:39,070
And then under the JWT manager,

13
00:00:39,070 --> 00:00:42,360
we're going to add some configuration.

14
00:00:42,360 --> 00:00:47,253
So we're gonna say, at JWT dot user claims loader.

15
00:00:48,512 --> 00:00:50,210
And then we're gonna add a new function,

16
00:00:50,210 --> 00:00:52,920
it doesn't matter what you call the function

17
00:00:52,920 --> 00:00:56,590
as long as it is under this decorator here

18
00:00:56,590 --> 00:01:00,653
and it takes in one parameter and must be called identity.

19
00:01:02,650 --> 00:01:06,280
This decorator here is going to modify the function

20
00:01:06,280 --> 00:01:10,260
below it at claims to JWT that's going to link it up

21
00:01:10,260 --> 00:01:13,800
with our JWT manager.

22
00:01:13,800 --> 00:01:16,873
The JWT manager, in turn, is linked up with our app.

23
00:01:18,530 --> 00:01:21,560
What's gonna happen is whenever we create

24
00:01:21,560 --> 00:01:25,440
a new access token, a new JWT,

25
00:01:25,440 --> 00:01:28,200
we're going to run this function to see

26
00:01:28,200 --> 00:01:32,653
if we should add any extra data to that JWT as well.

27
00:01:33,590 --> 00:01:34,530
Here's how it goes.

28
00:01:34,530 --> 00:01:36,880
Identity, of course, is,

29
00:01:36,880 --> 00:01:39,690
if we go back to our user login resource,

30
00:01:39,690 --> 00:01:43,815
identity is whatever we pass to the create access token

31
00:01:43,815 --> 00:01:45,660
and function.

32
00:01:45,660 --> 00:01:47,950
So if we're passing the user's ID

33
00:01:47,950 --> 00:01:49,350
to create access token,

34
00:01:49,350 --> 00:01:52,800
the identity parameter here is going to have the value

35
00:01:52,800 --> 00:01:56,480
of the user ID that we wanna add claims to.

36
00:01:56,480 --> 00:01:58,370
So we're gonna say a simple if statement

37
00:01:58,370 --> 00:02:00,433
if identity is equal to one,

38
00:02:01,650 --> 00:02:05,053
we're gonna return is admin is true.

39
00:02:06,020 --> 00:02:10,710
Otherwise, we're gonna return is admin is false.

40
00:02:10,710 --> 00:02:13,730
Just a simple claim here.

41
00:02:13,730 --> 00:02:17,940
If the user is the first user to be created in the database,

42
00:02:17,940 --> 00:02:20,190
we're gonna say they're an admin.

43
00:02:20,190 --> 00:02:23,200
If they are not, then we're gonna say they're not an admin.

44
00:02:23,200 --> 00:02:25,330
Okay, now, of course, I'm gonna add that comment

45
00:02:25,330 --> 00:02:26,280
just for completeness here.

46
00:02:26,280 --> 00:02:28,500
Instead of hard coding this,

47
00:02:28,500 --> 00:02:32,003
you should read from a config file or a database.

48
00:02:34,050 --> 00:02:39,050
Now, that I hope is fairly reasonable to you

49
00:02:39,200 --> 00:02:41,750
but instead of hard coding that your first user

50
00:02:41,750 --> 00:02:43,060
must be your admin,

51
00:02:43,060 --> 00:02:46,390
you should be reading this from database

52
00:02:46,390 --> 00:02:48,910
of your admin users that you can,

53
00:02:48,910 --> 00:02:52,603
of course, also create using your API and so forth.

54
00:02:55,129 --> 00:02:58,480
Now we've got this claim, we need to use the claim.

55
00:02:58,480 --> 00:03:01,093
So we're gonna go over to the user resource,

56
00:03:02,270 --> 00:03:04,650
sorry, the item resource, not the user resource.

57
00:03:04,650 --> 00:03:06,150
The item resource

58
00:03:06,150 --> 00:03:09,400
and in the delete function here,

59
00:03:09,400 --> 00:03:11,783
we're going to use the claims.

60
00:03:11,783 --> 00:03:15,070
All we have to do is, well of course, first thing,

61
00:03:15,070 --> 00:03:17,060
make the JWT required.

62
00:03:17,060 --> 00:03:19,533
So we're gonna say JWT required.

63
00:03:21,230 --> 00:03:24,810
Now that the JWT is required in this endpoint,

64
00:03:24,810 --> 00:03:26,943
whenever we run the endpoint,

65
00:03:27,800 --> 00:03:29,850
one of two things will happen.

66
00:03:29,850 --> 00:03:34,450
One, the user won't have sent a JWT.

67
00:03:34,450 --> 00:03:36,580
If they don't send the JWT,

68
00:03:36,580 --> 00:03:38,870
flask-JWT-extended is going to return an error

69
00:03:38,870 --> 00:03:40,977
and it's gonna say "unauthorised".

70
00:03:42,350 --> 00:03:46,610
The only other option is when they send a valid JWT,

71
00:03:46,610 --> 00:03:49,860
that means that by the time we're on this line,

72
00:03:49,860 --> 00:03:53,920
we have a JWT that is valid and that tells us

73
00:03:53,920 --> 00:03:57,200
that the person who send those requests is a user,

74
00:03:57,200 --> 00:03:59,403
a valid logged in user.

75
00:04:01,030 --> 00:04:02,520
Now we know we have a user here.

76
00:04:02,520 --> 00:04:04,840
All we have to do is say something like, claims is

77
00:04:04,840 --> 00:04:07,690
get JWT claims.

78
00:04:07,690 --> 00:04:10,260
Once again, this is going to link up to our flask gap

79
00:04:10,260 --> 00:04:13,410
and it's gonna get the data from the request

80
00:04:13,410 --> 00:04:14,660
that is coming in,

81
00:04:14,660 --> 00:04:17,960
it's going to interpret it, the JWT that's come in

82
00:04:17,960 --> 00:04:20,930
through the request and it's going to extract any claims

83
00:04:20,930 --> 00:04:22,833
that have been attached to that JWT.

84
00:04:24,830 --> 00:04:28,223
Then we can say, if not, claims is admin.

85
00:04:29,270 --> 00:04:32,130
Then we're gonna return a message saying, hey,

86
00:04:32,130 --> 00:04:34,023
you need to be an admin.

87
00:04:39,360 --> 00:04:40,193
That's it.

88
00:04:40,193 --> 00:04:44,133
That's all we have to do to add claims to a JWT.

89
00:04:46,130 --> 00:04:48,840
Let's delete data.db.

90
00:04:48,840 --> 00:04:52,840
I'm gonna delete that just to go back to user number one.

91
00:04:52,840 --> 00:04:55,403
And then we are going to run app.py.

92
00:04:56,460 --> 00:05:00,040
We can go over to Postman

93
00:05:01,330 --> 00:05:03,495
and we can go ahead and close these things.

94
00:05:03,495 --> 00:05:05,083
We're gonna register our new user.

95
00:05:06,280 --> 00:05:09,080
And this user is going to be user number one.

96
00:05:09,080 --> 00:05:12,680
We can double-check that by going to our new get endpoint.

97
00:05:12,680 --> 00:05:14,470
And getting user one, you can see that username

98
00:05:14,470 --> 00:05:16,078
is user three.

99
00:05:16,078 --> 00:05:17,403
That's the user we just created.

100
00:05:18,590 --> 00:05:21,533
We should now be able to both get an item,

101
00:05:23,570 --> 00:05:24,843
not enough segments.

102
00:05:26,430 --> 00:05:27,390
Of course, we didn't log in.

103
00:05:27,390 --> 00:05:29,190
We created a user but didn't log in.

104
00:05:30,382 --> 00:05:31,215
So there you have it.

105
00:05:31,215 --> 00:05:32,950
Now, we have an access token that's stored here

106
00:05:32,950 --> 00:05:35,180
in the environment.

107
00:05:35,180 --> 00:05:38,220
We can go ahead and get an item.

108
00:05:38,220 --> 00:05:40,423
Item not found so we're gonna create it.

109
00:05:42,017 --> 00:05:44,210
As we create it, we can go back and get it.

110
00:05:44,210 --> 00:05:45,170
It's there.

111
00:05:45,170 --> 00:05:48,430
Now, we can delete the item.

112
00:05:48,430 --> 00:05:49,683
This should just work.

113
00:05:51,210 --> 00:05:52,960
It doesn't work because we're missing

114
00:05:52,960 --> 00:05:54,290
an authorization header.

115
00:05:54,290 --> 00:05:56,960
So we're gonna go into the header's section

116
00:05:56,960 --> 00:05:59,950
and we're gonna add it here, authorization.

117
00:05:59,950 --> 00:06:01,563
And this is going to be better.

118
00:06:06,010 --> 00:06:06,843
There we go.

119
00:06:10,880 --> 00:06:15,723
So this is now getting us into our function.

120
00:06:17,000 --> 00:06:19,150
But of course, we forgot to import something

121
00:06:19,150 --> 00:06:21,330
or rather, I forgot to import something.

122
00:06:21,330 --> 00:06:23,490
So don't be like me.

123
00:06:23,490 --> 00:06:26,220
Don't forget to import your functions.

124
00:06:26,220 --> 00:06:29,010
So from flask-JWT-extended, make sure to import

125
00:06:29,010 --> 00:06:31,783
to the JWT required and get JWT claims.

126
00:06:33,330 --> 00:06:35,113
That's restarted our app.

127
00:06:36,000 --> 00:06:38,650
And look at what happens when we send this now again.

128
00:06:39,910 --> 00:06:40,743
Item deleted.

129
00:06:43,970 --> 00:06:46,760
This worked but it doesn't really tell us

130
00:06:46,760 --> 00:06:49,510
whether our claims did anything.

131
00:06:49,510 --> 00:06:50,343
Why?

132
00:06:50,343 --> 00:06:52,700
Because we need to test it with a user that is not

133
00:06:52,700 --> 00:06:54,103
an admin as well.

134
00:06:55,291 --> 00:06:57,320
We're gonna test with user two.

135
00:06:57,320 --> 00:07:00,210
We're gonna create a new user called user two.

136
00:07:00,210 --> 00:07:02,423
We're gonna log in as user two.

137
00:07:03,820 --> 00:07:05,890
It's gonna give us a new access token which is saved

138
00:07:05,890 --> 00:07:07,480
into our environment.

139
00:07:07,480 --> 00:07:10,510
And then, we are going to create a new item.

140
00:07:10,510 --> 00:07:12,030
This is fine, we can do that.

141
00:07:12,030 --> 00:07:13,850
And then we're gonna try to delete it.

142
00:07:13,850 --> 00:07:15,500
We should not be able to do this.

143
00:07:16,490 --> 00:07:17,590
And there you have it.

144
00:07:17,590 --> 00:07:19,230
Admin privilege required.

145
00:07:19,230 --> 00:07:22,850
It doesn't let us because when we created the JWT,

146
00:07:22,850 --> 00:07:26,703
we did not add the claim to say we're an admin.

147
00:07:27,550 --> 00:07:29,597
So going back to our app.py,

148
00:07:31,220 --> 00:07:33,150
I'm just gonna close this terminal here.

149
00:07:33,150 --> 00:07:37,840
We ran this function but the identity, the user ID,

150
00:07:37,840 --> 00:07:39,030
was two at this point.

151
00:07:39,030 --> 00:07:42,010
Not one because this is the second user we created

152
00:07:42,010 --> 00:07:45,150
and our ID is auto incrementing ID

153
00:07:45,150 --> 00:07:48,810
so what we returned is is admin false.

154
00:07:48,810 --> 00:07:50,720
In the delete,

155
00:07:50,720 --> 00:07:55,720
we then checked whether claims is admin evaluated to true.

156
00:07:56,410 --> 00:07:58,720
Well, if it didn't evaluate to true,

157
00:07:58,720 --> 00:08:01,480
we returned the message and so we did.

158
00:08:01,480 --> 00:08:04,010
The rest of this code, then, doesn't run

159
00:08:04,010 --> 00:08:05,840
because as soon as we return python, of course,

160
00:08:05,840 --> 00:08:09,003
we exit the function so this doesn't run here.

161
00:08:10,430 --> 00:08:13,080
That's how you add claims to a JWT

162
00:08:13,080 --> 00:08:15,470
and claims can be really useful for stuff like this

163
00:08:15,470 --> 00:08:17,050
and also for a number of other things.

164
00:08:17,050 --> 00:08:19,180
I'm sure you can come up with some examples

165
00:08:19,180 --> 00:08:22,720
on using claims in your own projects.

166
00:08:22,720 --> 00:08:23,890
I just wanted to tell you about it

167
00:08:23,890 --> 00:08:27,310
because it's straightforward using flask-JWT-extended

168
00:08:27,310 --> 00:08:31,840
and it can add a lot of functionality to your APIs.

169
00:08:31,840 --> 00:08:33,130
That's it for this video.

170
00:08:33,130 --> 00:08:34,580
I'll see you on the next one.

