Our API handler is now sending
the login details to the CMS,
and returning either the user "id" and "name",
or a "401 Unauthorized" response if the login failed.
What's left to do is set the cookie
with the JSON web token.
But before we do that
we could use that CMS_URL environment variable
that we define in our ".env" file.
Just like we do when fetching the product data.
This variable will be available in the API route
because it's server side code.
So let's insert this CMS_URL
into the argument we pass to fetchJson,
but for this to work we'll need
to make this string backtick-delimited.
Ok. Let's quickly test that
the API route still works.
Let's put the right password,
and we get a successful response,
so it clearly managed to call the CMS.
Now, it's time to take care of this cookie.
Setting a cookie can be done with a header,
so calling "setHeader" on the response,
and the header name is "Set-Cookie".
Now, the value will be a string,
but formatting a cookie value correctly
is not trivial.
So it's strongly recommended to use
a library to do that,
such as this one called "cookie".
This package can be used to "parse" cookies,
but what we need to do is "serialize" a cookie.
We can call "cookie.serialize"
passing a name and a value,
and possibly some options,
and this will return the properly formatted string.
So let's go and use this in our application.
We first need to install that package,
so let me stop the dev server.
And we can now run "npm install cookie".
It's been added to our dependencies.
So let's restart the dev server
and go back to our API handler code.
We now want to import that "cookie" module
that we just installed.
And with this we can call "cookie.serialize"
to prepare the value.
If we look at the signature of this method
it accepts the cookie name, its value,
and then some options.
The name could be "jwt",
and the value the "jwt" variable
that we got from the CMS response.
But we also want to pass an options object.
There are quite a few options we can set on a cookie,
but in this case we want to set the "path".
We could set it to "/",
which means the cookie will be sent back
to any page on our website.
But we'll only read the cookie in API routes,
so we could restrict it to the "/api" path.
All the API routes in a Next.js app
are under that path.
Now, we said we want to use a cookie
for saving the JSON web token for security reasons,
because we don't want client side code
to be able to read that token.
But for that to actually be the case
we need to set the "httpOnly" option to true.
This tells the browser to only send the cookie
as a header when making requests to the server,
but hide it from JavaScript code
running in the browser.
We could also set the "expires" option,
if we wanted the cookie to be remembered
for some amount of time.
But in this case I will not set an expiry,
which means it will be a "session cookie",
that is, it will only be remembered
until the user closes the browser.
That should be fine for this example.
If we make a request now,
you can see that the response includes
a "Set-Cookie" header,
and its value is "jwt=" and the token,
then at the end we can see the options,
separated by semicolons.
There is an official specification
dictating the format of this string,
but thankfully we don't need to worry about that.
We can simply use a library
that will produce the right output.
With this our API route is ready,
and we can call it from the SignInPage.
Instead of contacting the CMS directly,
we want to call "/api/login".
And in the request body, instead of "identifier"
we can simply pass the "email",
because we tailored the request input
for our own requirements.
Now, to test this we need to go back
to our website, in the browser.
Let's enter the usual email address,
and password.
Submit, and we can see the user "id" and "name"
logged to the console,
so it's clearly calling our API route.
But let's have a more in-depth look
at the network requests.
Here's the "login" request.
The URL is "/api/login" on port 3000.
And in the response headers
we can see the cookie being set,
with the JSON web token.
In fact, the dev tools also have a "Cookies" tab,
where we can see the same cookie,
but nicely presented in a table,
with each option in a separate column.
And the same cookie is also visible
under the Application tab.
This shows that it will be remembered
across different HTTP requests,
so that token will be sent back to the server
any time we make an API request.
This is a good point to take a break.
The SignInPage is now calling our API route,
so that we can receive the cookie
set by our API handler.
And in the following steps
we'll see what to do with this cookie.