The first part of your question is answered by: CORS with Postman.
For the second part, I came up with a very small code utilizing the concept of short-lived access tokens (that too simplified).
// utils/protector.js
let oldToken, newToken;
const checkToken = ({ headers: { 'x-access-token': token } }) =>
token && (token === oldToken || token === newToken);
const refreshToken = () => {
oldToken = newToken;
newToken = Math.random().toString(36).substr(2);
setTimeout(refreshToken, 3 * 60 * 60 * 1000); // each token is valid for 3 hrs
};
refreshToken();
export { checkToken, newToken as accessToken };
// api/user.js
import { checkToken } from '../../utils/protector';
const handler = (req, res) => {
// just add this line to the top of your handler
if (!checkToken(req)) return res.status(403).send();
// your API logic here...
res.status(200).json({ name: 'John Doe' });
};
export default handler;
Now in the page you wanna use a protected API:
// index.js
import { useState, useEffect } from 'react';
import { accessToken } from '../utils/protector';
const Home = ({ accessToken }) => {
const [user, setUser] = useState('Guest');
useEffect(() => {
// this will be called from the client
fetch('/api/user', { headers: { 'x-access-token': accessToken } })
.then((response) => response.json())
.then((data) => setUser(data.name));
return () => {};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return <div>Hello {user}!</div>;
};
const getServerSideProps = async () => {
return { props: { accessToken } };
};
export default Home;
export { getServerSideProps };
Any page using a protected route should be server side rendered, else the protector code will be bundled with the client side and will get executed in the browser, resulting in different tokens at the server side (APIs) and the client.
The concept of oldToken
and newToken
may appear quite unclear. Suppose:
A user visits your site at 11:59.
Your token gets refreshed at 00:00.
They triggered the API call at 12:01.
Now if there hadn't been an oldToken
, the newToken
would have changed before the call, and the response would have been a 403 Forbidden Error.
I have assumed a user takes exactly less than 3 hrs before they take an action on your page that invokes the protected API.
The timeout is set to 3 hrs, even if after a token is valid for twice its time because if the timeout is half (i.e. 1.5 hr) and the (above) user triggers the API call at 01:31. Then oldToken
is the newToken
, and newToken
is newer, both won't match what the user has.
Hence to guarantee that the received token will be valid atleast for 3 hrs, the total time to live is double. It may happen a token is valid for 6 hr (like for the user who visited the site at 12:00).