Next.js and csrf token returns server side error

I'm using the library next-csrf (https://github.com/j0lv3r4/next-csrf) to protect api routes in my next.js application.

I followed the documentation but the api now returns an error 500:

{"message":"Signed cookie string must be provided."}

Here's the code:

/lib/csrf.js:

import { nextCsrf } from 'next-csrf';

const options = {
  secret: `${process.env.CSRF_SECRET}`,
};

export const { csrf, csrfToken } = nextCsrf(options);

Page that calls the api:

import { useState, useEffect } from 'react';
import axios from 'axios';
import { withRouter } from 'next/router';

import { Page, PostBlock } from '@/components';


const Main = ({ router, csrfToken }) => {
  const [postsData, setPostsData] = useState({ posts: [], page: 0, pages: 0 });

  function fetchData() {
    axios
      .get('/api/articles', {
        headers: { 'XSRF-TOKEN': csrfToken },
        params: {
          page: router.query?.page,
          lang: router.locale,
          tag: router.query.tag,
        },
      })
      .then(response => {
        setPostsData(response.data);
      })
      .catch(error => console.log(error));
  }

  useEffect(() => {
    fetchData();
  }, []);


  return (
    <Page title='Home' className='home-template'>
      <div id='grid' className='post-grid'>
        {postsData.posts?.map(post => {=
          return (
            <PostBlock
              featured={post.featured}
              key={post.slug}
            />
          );
        })}
      </div>
    </Page>
  );
};

export default withRouter(Main);

The token works and I can see the header in the network tab:

enter image description here

Api route:

import { getPosts } from '../../../utils/index';

import { csrf } from '../../../lib/csrf';

function handler(req, res) {
  const {
    query: { page, lang, tag },
    method,
  } = req;

  switch (method) {
    case 'GET':
      const posts = getPosts(page, lang, tag);
      res.status(200).json(posts);
      break;
    default:
      break;
  }
}

export default csrf(handler);

There's also another thing happenig. If I try to call the api from postman the api works. I can see that there's a cookie with the "XSRF-TOKEN" value inside that I haven't set in any way, so I'm not sure where Postman is getting it:

enter image description here

How can I fix this?


  1. Such error message is possible only in the case when cookie value is not a string. And according to next-csrf getCookie code the cookie value may be not a string, only in case when there are some cookies but not the required one.

And there is an error in next-csrf transpilation which makes code from line 52 to move to the line 26, skipping some checks and changing the program logic. You can see it here https://unpkg.com/browse/[email protected]/dist/next-csrf.js, at the line 1891.

Now:

  • To avoid this case you should send first request without any cookie set up. It seems like this is what Postman does and this is why it works in Postman.
  • A fix in the code of getCookie is required. The function should return string, not string or undefined.

Also I wouldn't recommend you to use this library without proper transpilation issue resolution.

  1. Postman receives cookie, because next-csrf middleware defines set-cookie header, if there is no one in the first request.