next-auth: CLIENT_FETCH_ERROR - Unexpected token E in JSON at position 0

Environment

System: OS: macOS 13.3 CPU: (8) arm64 Apple M2 Memory: 1.25 GB / 16.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 16.17.0 - ~/.nvm/versions/node/v16.17.0/bin/node Yarn: 1.22.19 - ~/.nvm/versions/node/v16.17.0/bin/yarn npm: 9.6.3 - ~/development/nfts2me/nfts2me/node_modules/.bin/npm Browsers: Brave Browser: 105.1.43.93 Chrome: 112.0.5615.49 Firefox: 110.0.1 Safari: 16.4

Reproduction URL

not-available

Describe the issue

After upgrading from next-auth@4.20.1 to next-auth@4.21.1 we’re facing this error:

[next-auth][error][CLIENT_FETCH_ERROR] 
https://next-auth.js.org/errors#client_fetch_error invalid json response body at http://localhost:3000/api/auth/csrf/ reason: Unexpected token E in JSON at position 0 {
  error: {
    message: 'invalid json response body at http://localhost:3000/api/auth/csrf/ reason: Unexpected token E in JSON at position 0',
    stack: 'FetchError: invalid json response body at http://localhost:3000/api/auth/csrf/ reason: Unexpected token E in JSON at position 0\n' +
      '    at /nfts2me/node_modules/next/dist/compiled/node-fetch/index.js:1:51220\n' +
      '    at runMicrotasks (<anonymous>)\n' +
      '    at processTicksAndRejections (node:internal/process/task_queues:96:5)',
    name: 'FetchError'
  },
  url: 'http://localhost:3000/api/auth/csrf',
  message: 'invalid json response body at http://localhost:3000/api/auth/csrf/ reason: Unexpected token E in JSON at position 0'
}```

When trying to authenticate using Web3 provider (https://github.com/spruceid/siwe-next-auth-example).

The error happens on the "authorize" function on this line:
```          if (siwe.nonce !== (await getCsrfToken({ req }))) {```
When calling "getCsrfToken".

When rolling back to next-auth@4.20.1 it works with no problems.

### How to reproduce

Try to sign with Web3.

### Expected behavior

Authenticate.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 10
  • Comments: 19 (2 by maintainers)

Commits related to this issue

Most upvoted comments

So after thinking about it/having a look, this code block is the issue:

https://github.com/codingwithmanny/t3-app-siwe/blob/591fa139fb34cc63e377433794f9012407a13cf4/src/server/auth.ts#L148-L151

getCSRFToken is not very ideal on the backend, since it will invoke another endpoint and if you are using something like Vercel/Serverless, it might be the cause of slower response times.

Longer term, I would recommend finding an alternative solution, or as a workaround, instead of passing the whole req (which is a POST request with a body when in the authorize() call’s context), you can just pass an object with the cookies, since that’s the only things we need:

https://github.com/nextauthjs/next-auth/blob/7a8c0068c4c42761b54eff496f6cb8820b54b5d1/packages/next-auth/src/client/_utils.ts#L43

So this should solve the issue:

- const nonce = await getCsrfToken({ req });
+ const nonce = await getCsrfToken({ req: { headers: req.headers } });

This will make sure that the following code block is not triggered, making the response invalid: https://github.com/nextauthjs/next-auth/blob/7a8c0068c4c42761b54eff496f6cb8820b54b5d1/packages/next-auth/src/client/_utils.ts#L47-L50

I would consider this kind of an edge case/not something we have official built-in support for, so I’m inclined to close the issue as it’s not a bug, but I hope my above suggestion will be sufficient.

have exactly the same issue.

Seems like getCsrfToken in the authorize method is throwing error

How To Reproduce

1 - Scaffold new project - pnpm create t3-app@latest; 2 - Modify ./src/server/auth.ts under the getServerAuthSession as follows:

File: ./src/server/auth.ts

// ...

// NOTE: This is needed for passing the `req` to the authOptions to verify the csrf with the nonce for Sign-In With Ethereum

/**
 * Wrapper for `getServerSession` so that you don't need to import the `authOptions` in every file.
 *
 * @see https://next-auth.js.org/configuration/nextjs
 */
export const getServerAuthSession = async (ctx: {
  req: GetServerSidePropsContext["req"];
  res: GetServerSidePropsContext["res"];
}) => {
  // Add next two lines to retrieve csrf token
  const token = await getCsrfToken({ req: ctx.req });
  console.log({ token });
  return getServerSession(ctx.req, ctx.res, authOptions);
};

3 - Run the dev environment and see error in terminal - pnpm dev

Expected Behavior

With version next-auth@4.20.1

pnpm dev;

# Output:
# {
#   token: '2f9e2ad7596966b47e4d631ad3cbe48d246781b91f8680a840906a02529aacb3'
# }

Current Behavior

With version next-auth@4.21.1

pnpm dev;

# Output:
# [next-auth][error][CLIENT_FETCH_ERROR] 
# https://next-auth.js.org/errors#client_fetch_error invalid json response body at http://localhost:3000/api/auth/csrf reason: # Unexpected token E in JSON at position 0 {
#   error: {
#     message: 'invalid json response body at http://localhost:3000/api/auth/csrf reason: Unexpected token E in JSON at # position 0',
#     stack: 'FetchError: invalid json response body at http://localhost:3000/api/auth/csrf reason: Unexpected token E in JSON # at position 0\n' +
#       '    at /Users/username/path/to/test-t3-app/node_modules/.pnpm/next@13.2.4_react-# dom@18.2.0_react@18.2.0/node_modules/next/dist/compiled/node-fetch/index.js:1:51220\n' +
#       '    at runMicrotasks (<anonymous>)\n' +
#       '    at processTicksAndRejections (node:internal/process/task_queues:96:5)',
#     name: 'FetchError'
#   },
#   url: 'http://localhost:3000/api/auth/csrf',
#   message: 'invalid json response body at http://localhost:3000/api/auth/csrf reason: Unexpected token E in JSON at # position 0'
# }
# { token: undefined }
- const nonce = await getCsrfToken({ req });
+ const nonce = await getCsrfToken({ req: { headers: req.headers } });

I was re-checking the docs, and I still think that NextAuth introduced a bug, or the docs are wrong: Check this: https://next-auth.js.org/getting-started/client#server-side-example It explicitly gives the example for the server side to be done as the ‘wrong?’ code.

I would be nice to change either.

Getting the same issue after installing v4.21.1 reverted back to 4.20.1 to ensure things are working.

I get the same Error when I invoke await getCsrfToken({ req }) inside the authorize method of a credentials provider. I think I found the issue or at least some more details why this happens.

The original error when decoding the response, in fetchData which is invoked by getCsrfToken, to text instead of json, it says: Error: This action with HTTP POST is not supported by NextAuth.js

In fetchData there is a check if the request has a body

if (req?.body) {
      options.body = JSON.stringify(req.body)
      options.method = "POST"
    }

if so, fetching the Csrf-Token is done with a POST request which doesnt seem to work. You can check when running a POST request to http://localhost:3000/api/auth/csrf it responses with Error: This action with HTTP POST is not supported by NextAuth.js

Maybe the fetchData method has changed and introduced this bug?

I was facing the same issue in production when I was trying to deploy to Vercel. What worked for me was turning off the Vercel Authentication in Project Settings > Deployment Protection. Hope this helps!

Absolutely @balazsorban44 Here is a repository: https://github.com/codingwithmanny/t3-app-siwe

The only thing that needs to be done is update the version pnpm add next-auth@latest. The README should show how to set it up.

For some additional context, this is an implementation with Sign-In With Ethereum (SIWE) and Create-t3-stack, and it’ll require a Crypto wallet like https://metamask.io.

The way that we’re leverage getCsrfToken is to leverage and use as a nonce needed for the SIWE wallet message prompt.

Good morning I was managed to resolve an issue by using const session = await getServerAuthSession(context); instead of const session = await getSession(context);

The issue still persists w/ on next-auth with app dir

const nonce = await getCsrfToken({ req: { headers: req.headers } });

Resolved w/ downgrade as the comment above