1
00:00:03,000 --> 00:00:05,583
Our API handler is now sending

2
00:00:05,583 --> 00:00:08,080
the login details to the CMS,

3
00:00:08,080 --> 00:00:12,041
and returning either the user "id" and "name",

4
00:00:12,041 --> 00:00:16,605
or a "401 Unauthorized" response if the login failed.

5
00:00:16,605 --> 00:00:19,619
What's left to do is set the cookie

6
00:00:19,619 --> 00:00:21,686
with the JSON web token.

7
00:00:22,617 --> 00:00:24,191
But before we do that

8
00:00:24,191 --> 00:00:27,639
we could use that CMS_URL environment variable

9
00:00:27,639 --> 00:00:30,188
that we define in our ".env" file.

10
00:00:30,838 --> 00:00:33,547
Just like we do when fetching the product data.

11
00:00:34,070 --> 00:00:37,523
This variable will be available in the API route

12
00:00:37,523 --> 00:00:39,681
because it's server side code.

13
00:00:40,253 --> 00:00:42,532
So let's insert this CMS_URL

14
00:00:42,532 --> 00:00:45,706
into the argument we pass to fetchJson,

15
00:00:46,287 --> 00:00:48,127
but for this to work we'll need

16
00:00:48,127 --> 00:00:50,440
to make this string backtick-delimited.

17
00:00:51,000 --> 00:00:52,873
Ok. Let's quickly test that

18
00:00:52,873 --> 00:00:54,677
the API route still works.

19
00:00:55,432 --> 00:00:56,887
Let's put the right password,

20
00:00:58,432 --> 00:01:00,792
and we get a successful response,

21
00:01:00,792 --> 00:01:03,508
so it clearly managed to call the CMS.

22
00:01:04,078 --> 00:01:06,855
Now, it's time to take care of this cookie.

23
00:01:07,355 --> 00:01:09,969
Setting a cookie can be done with a header,

24
00:01:09,969 --> 00:01:12,341
so calling "setHeader" on the response,

25
00:01:12,902 --> 00:01:15,176
and the header name is "Set-Cookie".

26
00:01:16,768 --> 00:01:18,931
Now, the value will be a string,

27
00:01:18,931 --> 00:01:21,567
but formatting a cookie value correctly

28
00:01:21,567 --> 00:01:22,581
is not trivial.

29
00:01:23,216 --> 00:01:25,723
So it's strongly recommended to use

30
00:01:25,723 --> 00:01:27,228
a library to do that,

31
00:01:27,228 --> 00:01:29,591
such as this one called "cookie".

32
00:01:30,234 --> 00:01:32,876
This package can be used to "parse" cookies,

33
00:01:33,376 --> 00:01:36,986
but what we need to do is "serialize" a cookie.

34
00:01:37,486 --> 00:01:39,528
We can call "cookie.serialize"

35
00:01:39,528 --> 00:01:41,366
passing a name and a value,

36
00:01:41,366 --> 00:01:43,135
and possibly some options,

37
00:01:43,135 --> 00:01:46,606
and this will return the properly formatted string.

38
00:01:47,310 --> 00:01:49,567
So let's go and use this in our application.

39
00:01:50,067 --> 00:01:52,260
We first need to install that package,

40
00:01:52,260 --> 00:01:53,992
so let me stop the dev server.

41
00:01:55,033 --> 00:01:58,141
And we can now run "npm install cookie".

42
00:02:02,166 --> 00:02:03,638
It's been added to our dependencies.

43
00:02:04,138 --> 00:02:06,454
So let's restart the dev server

44
00:02:06,454 --> 00:02:09,144
and go back to our API handler code.

45
00:02:10,437 --> 00:02:13,225
We now want to import that "cookie" module

46
00:02:13,225 --> 00:02:14,751
that we just installed.

47
00:02:17,271 --> 00:02:20,057
And with this we can call "cookie.serialize"

48
00:02:20,057 --> 00:02:21,387
to prepare the value.

49
00:02:22,905 --> 00:02:25,483
If we look at the signature of this method

50
00:02:25,483 --> 00:02:27,815
it accepts the cookie name, its value,

51
00:02:27,815 --> 00:02:29,166
and then some options.

52
00:02:29,788 --> 00:02:31,550
The name could be "jwt",

53
00:02:31,550 --> 00:02:33,898
and the value the "jwt" variable

54
00:02:33,898 --> 00:02:36,394
that we got from the CMS response.

55
00:02:37,040 --> 00:02:39,549
But we also want to pass an options object.

56
00:02:40,049 --> 00:02:42,359
There are quite a few options we can set on a cookie,

57
00:02:42,859 --> 00:02:45,781
but in this case we want to set the "path".

58
00:02:45,781 --> 00:02:47,344
We could set it to "/",

59
00:02:47,344 --> 00:02:50,062
which means the cookie will be sent back

60
00:02:50,062 --> 00:02:51,897
to any page on our website.

61
00:02:52,600 --> 00:02:56,113
But we'll only read the cookie in API routes,

62
00:02:56,113 --> 00:02:59,469
so we could restrict it to the "/api" path.

63
00:02:59,469 --> 00:03:02,201
All the API routes in a Next.js app

64
00:03:02,201 --> 00:03:03,762
are under that path.

65
00:03:04,497 --> 00:03:07,192
Now, we said we want to use a cookie

66
00:03:07,192 --> 00:03:11,011
for saving the JSON web token for security reasons,

67
00:03:11,011 --> 00:03:13,856
because we don't want client side code

68
00:03:13,856 --> 00:03:16,103
to be able to read that token.

69
00:03:16,828 --> 00:03:19,394
But for that to actually be the case

70
00:03:19,394 --> 00:03:22,601
we need to set the "httpOnly" option to true.

71
00:03:22,601 --> 00:03:25,880
This tells the browser to only send the cookie

72
00:03:25,880 --> 00:03:29,230
as a header when making requests to the server,

73
00:03:29,230 --> 00:03:31,511
but hide it from JavaScript code

74
00:03:31,511 --> 00:03:33,150
running in the browser.

75
00:03:34,007 --> 00:03:36,601
We could also set the "expires" option,

76
00:03:36,601 --> 00:03:39,263
if we wanted the cookie to be remembered

77
00:03:39,263 --> 00:03:40,859
for some amount of time.

78
00:03:41,492 --> 00:03:44,086
But in this case I will not set an expiry,

79
00:03:44,086 --> 00:03:46,679
which means it will be a "session cookie",

80
00:03:47,240 --> 00:03:49,480
that is, it will only be remembered

81
00:03:49,480 --> 00:03:51,656
until the user closes the browser.

82
00:03:52,219 --> 00:03:54,091
That should be fine for this example.

83
00:03:54,591 --> 00:03:56,012
If we make a request now,

84
00:03:56,991 --> 00:03:59,922
you can see that the response includes

85
00:03:59,922 --> 00:04:01,619
a "Set-Cookie" header,

86
00:04:01,619 --> 00:04:04,550
and its value is "jwt=" and the token,

87
00:04:04,550 --> 00:04:07,558
then at the end we can see the options,

88
00:04:07,558 --> 00:04:09,410
separated by semicolons.

89
00:04:09,410 --> 00:04:12,032
There is an official specification

90
00:04:12,032 --> 00:04:14,809
dictating the format of this string,

91
00:04:15,771 --> 00:04:18,606
but thankfully we don't need to worry about that.

92
00:04:18,606 --> 00:04:20,168
We can simply use a library

93
00:04:20,168 --> 00:04:22,193
that will produce the right output.

94
00:04:22,808 --> 00:04:24,946
With this our API route is ready,

95
00:04:24,946 --> 00:04:27,473
and we can call it from the SignInPage.

96
00:04:28,037 --> 00:04:31,051
Instead of contacting the CMS directly,

97
00:04:31,051 --> 00:04:33,291
we want to call "/api/login".

98
00:04:33,868 --> 00:04:36,687
And in the request body, instead of "identifier"

99
00:04:36,687 --> 00:04:38,507
we can simply pass the "email",

100
00:04:39,065 --> 00:04:41,392
because we tailored the request input

101
00:04:41,392 --> 00:04:42,965
for our own requirements.

102
00:04:43,527 --> 00:04:45,775
Now, to test this we need to go back

103
00:04:45,775 --> 00:04:47,710
to our website, in the browser.

104
00:04:48,793 --> 00:04:50,699
Let's enter the usual email address,

105
00:04:52,426 --> 00:04:53,362
and password.

106
00:04:53,992 --> 00:04:57,336
Submit, and we can see the user "id" and "name"

107
00:04:57,336 --> 00:04:58,901
logged to the console,

108
00:04:58,901 --> 00:05:01,604
so it's clearly calling our API route.

109
00:05:02,246 --> 00:05:04,772
But let's have a more in-depth look

110
00:05:04,772 --> 00:05:06,503
at the network requests.

111
00:05:07,679 --> 00:05:10,248
Here's the "login" request.

112
00:05:10,248 --> 00:05:13,768
The URL is "/api/login" on port 3000.

113
00:05:14,363 --> 00:05:16,062
And in the response headers

114
00:05:16,062 --> 00:05:18,076
we can see the cookie being set,

115
00:05:18,076 --> 00:05:19,586
with the JSON web token.

116
00:05:20,211 --> 00:05:23,420
In fact, the dev tools also have a "Cookies" tab,

117
00:05:23,920 --> 00:05:25,890
where we can see the same cookie,

118
00:05:25,890 --> 00:05:27,800
but nicely presented in a table,

119
00:05:27,800 --> 00:05:30,068
with each option in a separate column.

120
00:05:30,687 --> 00:05:33,075
And the same cookie is also visible

121
00:05:33,075 --> 00:05:34,849
under the Application tab.

122
00:05:35,418 --> 00:05:38,124
This shows that it will be remembered

123
00:05:38,124 --> 00:05:40,392
across different HTTP requests,

124
00:05:40,966 --> 00:05:44,301
so that token will be sent back to the server

125
00:05:44,301 --> 00:05:46,673
any time we make an API request.

126
00:05:47,247 --> 00:05:49,805
This is a good point to take a break.

127
00:05:50,305 --> 00:05:53,463
The SignInPage is now calling our API route,

128
00:05:53,963 --> 00:05:56,441
so that we can receive the cookie

129
00:05:56,441 --> 00:05:58,167
set by our API handler.

130
00:05:58,742 --> 00:06:00,227
And in the following steps

131
00:06:00,227 --> 00:06:02,396
we'll see what to do with this cookie.

