1
00:00:03,000 --> 00:00:05,632
At this point our NavBar component

2
00:00:05,632 --> 00:00:08,186
is calling the "/api/user" route,

3
00:00:08,765 --> 00:00:11,696
and can display the user name in the header,

4
00:00:11,696 --> 00:00:13,895
along with the "Sign Out" button.

5
00:00:14,461 --> 00:00:17,249
The only thing that's still missing is that

6
00:00:17,249 --> 00:00:19,778
if we click "Sign Out" nothing happens.

7
00:00:20,343 --> 00:00:22,750
So let's go and add that functionality.

8
00:00:23,250 --> 00:00:26,158
On this "button" we want to add an event handler,

9
00:00:27,115 --> 00:00:28,320
that is "onClick",

10
00:00:29,416 --> 00:00:31,475
and here we can pass a function

11
00:00:31,475 --> 00:00:33,003
called "handleSignOut",

12
00:00:33,003 --> 00:00:34,531
that we need to create.

13
00:00:35,749 --> 00:00:38,108
Let's put it after all the hooks,

14
00:00:38,108 --> 00:00:40,824
and before returning the JSX elements.

15
00:00:42,481 --> 00:00:44,481
Now, let's think for a moment

16
00:00:44,481 --> 00:00:46,962
what we need to do in this function.

17
00:00:46,962 --> 00:00:48,962
We want to delete the cookie.

18
00:00:49,600 --> 00:00:52,518
But remember that, for security reasons,

19
00:00:52,518 --> 00:00:55,510
we are setting this cookie as "httpOnly".

20
00:00:56,082 --> 00:00:59,114
So it's not possible to modify the cookie

21
00:00:59,114 --> 00:01:00,667
from the client side.

22
00:01:00,667 --> 00:01:03,773
We can only do that from server side code.

23
00:01:04,420 --> 00:01:06,577
This means we'll need to create

24
00:01:06,577 --> 00:01:09,012
another API route for the "logout",

25
00:01:09,012 --> 00:01:11,099
in order to remove the cookie.

26
00:01:11,739 --> 00:01:13,982
This will be another handler function,

27
00:01:13,982 --> 00:01:15,693
let's call it "handleLogout",

28
00:01:19,272 --> 00:01:22,192
and we can start with the usual 200 response

29
00:01:22,192 --> 00:01:23,918
with an empty JSON object.

30
00:01:24,484 --> 00:01:26,566
I should have written a user snippet

31
00:01:26,566 --> 00:01:28,070
for this boilerplate code.

32
00:01:28,718 --> 00:01:31,627
But anyway, how do we delete a cookie now?

33
00:01:32,127 --> 00:01:34,127
That's actually pretty similar to

34
00:01:34,127 --> 00:01:36,612
how we set the cookie in the first place.

35
00:01:37,173 --> 00:01:40,535
So let's start by importing the "cookie" module

36
00:01:40,535 --> 00:01:42,181
into our new API route.

37
00:01:42,753 --> 00:01:44,544
And then we can go and copy

38
00:01:44,544 --> 00:01:47,065
the code that sets the cookie as well.

39
00:01:48,586 --> 00:01:51,352
Here we want to chain the "setCookie" call

40
00:01:51,352 --> 00:01:52,868
on the response object.

41
00:01:53,986 --> 00:01:55,487
Now, to delete a cookie

42
00:01:55,487 --> 00:01:58,099
we can set its value to an empty string,

43
00:01:58,665 --> 00:02:00,538
and we want to keep the same "path",

44
00:02:01,038 --> 00:02:03,645
but the most important thing is that

45
00:02:03,645 --> 00:02:06,179
we need to set the "expires" option

46
00:02:06,752 --> 00:02:08,676
to be a Date in the past.

47
00:02:08,676 --> 00:02:11,682
So we're basically telling the browser:

48
00:02:11,682 --> 00:02:15,456
this cookie is expired, so you should discard it.

49
00:02:16,111 --> 00:02:18,833
Now, I'm passing "new Date(0)" here

50
00:02:18,833 --> 00:02:21,243
because this will create a date

51
00:02:21,243 --> 00:02:23,810
at 0 milliseconds past the epoch,

52
00:02:24,466 --> 00:02:27,403
so this results in January 1st 1970,

53
00:02:27,403 --> 00:02:30,667
which is the epoch for JavaScript dates.

54
00:02:31,248 --> 00:02:34,709
The important thing is that it's a date in the past,

55
00:02:35,209 --> 00:02:36,928
which will tell the browser

56
00:02:36,928 --> 00:02:39,158
that the cookie is already expired.

57
00:02:39,722 --> 00:02:42,459
Ok. Now that we have our new API route,

58
00:02:42,459 --> 00:02:45,336
we can call it from the NavBar component.

59
00:02:45,907 --> 00:02:47,913
When the user clicks "Sign Out"

60
00:02:47,913 --> 00:02:49,402
we can call "fetchJson"

61
00:02:50,240 --> 00:02:54,152
and request the "/api/logout" route.

62
00:02:54,652 --> 00:02:56,726
Let's make this function "async"

63
00:02:56,726 --> 00:03:00,097
so we can "await" the "fetchJson" response as usual.

64
00:03:00,097 --> 00:03:02,884
We're not actually going to use the result,

65
00:03:02,884 --> 00:03:05,153
that's just an empty object anyway.

66
00:03:05,848 --> 00:03:08,769
But we still want to wait for the response,

67
00:03:08,769 --> 00:03:09,992
because after that

68
00:03:10,560 --> 00:03:13,690
we want to update the "user" state variable,

69
00:03:13,690 --> 00:03:16,679
so that this component will be re-rendered

70
00:03:16,679 --> 00:03:19,525
and show that we're no longer signed in.

71
00:03:20,168 --> 00:03:22,966
In practice we want to call "setUser"

72
00:03:22,966 --> 00:03:25,841
and pass "undefined" as the new value.

73
00:03:26,417 --> 00:03:29,342
This way we effectively re-set the state

74
00:03:29,342 --> 00:03:30,877
to its initial value.

75
00:03:30,877 --> 00:03:33,730
If the "user" variable is a falsy value

76
00:03:33,730 --> 00:03:36,289
that means we're not authenticated.

77
00:03:37,009 --> 00:03:39,550
Ok. It's time to try if this works.

78
00:03:40,050 --> 00:03:42,872
I want to keep an eye on the network requests

79
00:03:42,872 --> 00:03:44,628
so let me open the right tab

80
00:03:44,628 --> 00:03:46,509
in the Chrome Developer Tools.

81
00:03:47,150 --> 00:03:49,667
Ok. Now, if we click "Sign Out",

82
00:03:49,667 --> 00:03:53,366
you can see that the NavBar immediately updated

83
00:03:53,366 --> 00:03:56,356
and is now showing the "Sign In" link,

84
00:03:56,356 --> 00:03:58,480
so we have been signed out.

85
00:03:59,217 --> 00:04:01,394
And if we look at the Dev Tools

86
00:04:01,394 --> 00:04:03,291
it made a "logout" request,

87
00:04:03,862 --> 00:04:06,703
which is of course a call to our API route.

88
00:04:07,203 --> 00:04:10,340
Here we can see the "Set-Cookie" header

89
00:04:10,340 --> 00:04:12,351
returned in the response.

90
00:04:12,351 --> 00:04:15,247
It does says "Expires: 01 Jan 1970".

91
00:04:15,908 --> 00:04:19,252
As a result the cookie should have been removed.

92
00:04:19,252 --> 00:04:22,317
This tab just shows that the response cookie

93
00:04:22,317 --> 00:04:23,641
had an empty value,

94
00:04:24,281 --> 00:04:26,571
but if we look at the Application tab,

95
00:04:26,571 --> 00:04:29,585
here you can see that there is no cookie any more.

96
00:04:30,146 --> 00:04:32,687
So it has been discarded by the browser.

97
00:04:34,646 --> 00:04:36,933
All right, this concludes this section

98
00:04:36,933 --> 00:04:38,197
about authentication.

99
00:04:38,758 --> 00:04:40,789
We've seen how to log out

100
00:04:40,789 --> 00:04:44,609
by removing the jwt cookie from an API handler,

101
00:04:44,609 --> 00:04:47,779
that is setting its expiry in the past.

102
00:04:47,779 --> 00:04:51,355
Even though our authentication functionality

103
00:04:51,355 --> 00:04:52,981
is now working fine,

104
00:04:52,981 --> 00:04:55,338
in the next section we'll see

105
00:04:55,338 --> 00:04:57,776
how we can cache API responses

106
00:04:57,776 --> 00:05:00,539
and generally improve all the code

107
00:05:00,539 --> 00:05:04,197
that makes HTTP requests from the client side

108
00:05:04,197 --> 00:05:07,285
by using a library called React Query.

