A known problem with JWT authentication is that persisting to local storage introduces a security issue. An improvement is made by using HTTP-only cookies on the server side. The Next.js native API provides a means to easily implement this feature.
-
The Basic Express API (https://github.com/stefaleon/Basic-Express-API) is used as the external back-end.
-
The axios calls in the Next API methods are made towards URLs adjusted to the specific external API.
The topics below refer to the project commits with the same name
- Use the Next back-end as an intermediary for the requests we make from the app, in order to have the same-origin policy applied and avoid CORS related issues.
- Test with Postman with POST to http://localhost:3000/api/register
body
{
"name" : "test",
"email": "test@test.com",
"password": "111111"
}
- Test with Postman with POST to http://localhost:3000/api/login
body
{
"email": "test@test.com",
"password": "111111"
}
- Wrap the app Component in _app.js with AuthProvider in order to have the auth state values available throughout the app
- Hide the link to the protected page if "user" is not available in the auth state.
- Display "Logout" instead of "Login" if "user" is available in the auth state.
- Even though the related link is hidden in the navbar, the protected page is currently accessible by entering the related url (http://localhost:3000/protected) manually in the browser's address bar.
- To fix this, redirect to the login page if "user" is not available in the auth state.
- Set the cookie in the response headers as we login. It now becomes available in
req.headers.cookie. - Confirm the availability for subsequent requests by use of the checkCookie Next API route.
- Check if "user" exists in state on each AuthProvider load. Do so by calling the
/api/userroute in the Next API, which in turn calls theapi/users/meroute in the external Express API. - The request to the external API contains the JWT in the headers, which is extracted by parsing the
req.headers.cookie. - If the check fails, set "user" to null and, if we are in a protected route, redirect to login page.
- Since the server side HTTP-only cookie persists, the log out functionality is broken. If we refresh, we still have the cookie in the browser storage.
- In order to properly log out, we need to set antoher cookie with its expiration set to 0.