Next.js Authentication with JWT Next.js Authentication with JWT express express

Next.js Authentication with JWT


My answer is purely based on my experiences and things I read. Feel free to correct it if I happened to be wrong.

So, my way is to store your token in HttpOnly cookie, and always use that cookie to authorize your requests to the Node API via Authorization header. I happen to also use Node.js API in my own project, so I know what's going on.

Following is an example of how I usually handle authentication with Next.js and Node.js API.

In order to ease up authentication problems, I'm using Next.js's built in getServerSideProps function in a page to build a new reusable higher order component that will take care of authentication. In this case, I will name it isLoggedIn.

// isLoggedIn.jsxexport default (GetServerSidePropsFunction) => async (ctx) => {  // 1. Check if there is a token in cookies. Let's assume that your JWT is stored in 'jwt'.  const token = ctx.req.cookies?.jwt || null;  // 2. Perform an authorized HTTP GET request to the private API to check if the user is genuine.  const { data } = await authenticate(...); // your code here...  // 3. If there is no user, or the user is not authenticated, then redirect to homepage.  if (!data) {    return {      redirect: {        destination: '/',        permanent: false,      },    };  }  // 4. Return your usual 'GetServerSideProps' function.  return await GetServerSidePropsFunction(ctx);};

getServerSideProps will block rendering until the function has been resolved, so make sure your authentication is fast and does not waste much time.

You can use the higher order component like this. Let's call this one profile.jsx, for one's profile page.

// profile.jsxexport default isLoggedIn(async (ctx) => {  // In this component, do anything with the authorized user. Maybe getting his data?  const token = ctx.req.cookies.jwt;  const { data } = await getUserData(...); // don't forget to pass his token in 'Authorization' header.  return {    props: {      data,    },  },});

This should be secure, as it is almost impossible to manipulate anything that's on server-side, unless one manages to find a way to breach into your back-end.

If you want to make a POST request, then I usually do it like this.

// profile.jsxconst handleEditProfile = async (e) => {  const apiResponse = await axios.post(API_URL, data, { withCredentials: true });    // do anything...};

In a POST request, the HttpOnly cookie will also be sent to the server, because of the withCredentials parameter being set to true.

There is also an alternative way of using Next.js's serverless API to send the data to the server. Instead of making a POST request to the API, you'll make a POST request to the 'proxy' Next.js's serverless API, where it will perform another POST request to your API.


Authentication can be made in many ways, since you did not share any code, I will give you a hint, so you can apply to your code.

cookies are just for storing information. They are not just related to authentication. you can store jwt inside the cookie. Since next.js a framework that handles the client and server, each request from client part will be made to server part. As you know, you send the authentication token along side the request.

Based on your question, you will make external api request via the serverless functions. inside "pages" folder, we have api folder and write all api requests here. So when you want to send request from client, you will make request to those, api functions. Inside this functions you will handle the request. this is where next.js talks to external api's.

Key thing here, when you send the jwt token from the client, you need to extract it here. Then you have to add it to your external api request. this is a how logic should be :

async serverlessAuth(req) {    let verifiedToken;    if (req.headers.cookie) {      const token = getCookieFromReq(req, "jwt"); // this logic depends on how you store your jwt. getCookieFromReq, i just named it like that.       verifiedToken = await this.verifyToken(token);      return verifiedToken;    }    return undefined;  }  ... then use this token to make api request} 

Let is say inside a page, you make a request.

 const { data, loading,error } = useGetUser() // you write your logic here

inside this useGetUser(), it will make request to pages/api/v1/user.js, result will be returned here.