Missing state cookie from login request (yes, another one!)

Description

I’m seeing this error come up LOTS in the forums and online recently. It’d be great if Auth0 engineers, etc. could explain what causes it. For me it just started happening one day and there are 2 things I did which could cause it:

  1. I added a middleware function
  2. I did a manual reset of the application (storage, cookies, etc.)

IDK if these are the things that threw the app out of sync state-wise?


Setup

I’m using:
Node version: 16, 18 or 20 and "@auth0/nextjs-auth0": "^3.1.0",

In api/auth/[...auth0].js I have:

import { handleAuth } from "@auth0/nextjs-auth0";
const auth = handleAuth();
export default auth;

I’m using a AuthRedirectWrapper from the docs.

import { useState, useRef } from "react";
import { useUser } from "@auth0/nextjs-auth0/client";
import Router from "next/router";
import CircularProgress from "@mui/material/CircularProgress";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";

type AuthRedirectWrapperProps = {
  children: React.ReactNode;
};

export default function AuthRedirectWrapper({
  children,
}: AuthRedirectWrapperProps): JSX.Element | null {

  const isServerSide = typeof window === "undefined";
  const isClientSide = !isServerSide;
  const loginPath = "/api/auth/login";

  const { user, error, isLoading }  = useUser();

  if (isLoading) {
    // console.log("loading case");
    return (
      <Box sx={{ display: "grid", height: '100vh', placeContent: 'center' }}>
        <CircularProgress />
      </Box>
    );
  }

  if (error) {
    return (
      <Box sx={{ display: "flex" }}>
        <Typography variant="h1" gutterBottom>
          Error
        </Typography>
        <Typography variant="body1" gutterBottom>
          {JSON.stringify(error)}
        </Typography>
      </Box>
    );
  }

  if (!user && isClientSide) {
    if (Router.asPath !== loginPath) {
      Router.push(loginPath);
    }

    return null;
  }
  // console.log("rendering normally");
  return <>{children}</>;
}

I’m also using a middleware that looks like this:

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  // Clone the request headers and set a new header `x-hello-from-middleware1`
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set("x-hello-from-middleware1", "hello");

  // You can also set request headers in NextResponse.rewrite
  const response = NextResponse.next({
    request: {
      // New request headers
      headers: requestHeaders,
    },
  });
  // console.log("called james route");
  // Set a new response header `x-hello-from-middleware2`
  response.headers.set("x-hello-from-middleware2", "hello");
  return response;
}

export const config = {
  matcher: '/courses/:course/:tutor*',
}

Call sequence

  1. GET http://localhost:3000/api/auth/login 302 (there is a first one of these that gets cancelled - I think that may be due to being on the development server and getting the double load?)

  2. GET https://dev-24zlwfwr3qaop7nz.uk.auth0.com/authorize?client_id=RbZMV5ttNmP5DLNy1ycXyQ9Dcv4AZxdA&scope=openid%20profile%20email&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fauth%2Fcallback&nonce=pe7a5EluRHUwvwQ8qFXy1MPIXiLwt88FCfMYFHbn0D0&state=eyJyZXR1cm5UbyI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMCJ9&code_challenge_method=S256&code_challenge=H0EdHMXZiGkKhNMa4NcJOj82cTlMJCm_j0amGf_alwg 302

  3. GET http://localhost:3000/api/auth/callback?code=2RvjmkVcyxF_cGy43coShUOE40Mv0rURWAh3rDHtX7xIV&state=eyJyZXR1cm5UbyI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMCJ9 400


Result (in Server Logs)

CallbackHandlerError: Callback handler failed. CAUSE: Missing state cookie from login request (check login URL, callback URL and cookie config).
    at /Users/jamessherry/sites/new-jump/student-portal-next-sanity/node_modules/.pnpm/@auth0+nextjs-auth0@3.1.0_next@13.4.16/node_modules/@auth0/nextjs-auth0/dist/handlers/callback.js:74:15
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async /Users/jamessherry/sites/new-jump/student-portal-next-sanity/node_modules/.pnpm/@auth0+nextjs-auth0@3.1.0_next@13.4.16/node_modules/@auth0/nextjs-auth0/dist/handlers/auth.js:79:13 {
  code: 'ERR_CALLBACK_HANDLER_FAILURE',
  cause: MissingStateCookieError: Missing state cookie from login request (check login URL, callback URL and cookie config).
      at /Users/jamessherry/sites/new-jump/student-portal-next-sanity/node_modules/.pnpm/@auth0+nextjs-auth0@3.1.0_next@13.4.16/node_modules/@auth0/nextjs-auth0/dist/auth0-session/handlers/callback.js:17:19
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
      at async /Users/jamessherry/sites/new-jump/student-portal-next-sanity/node_modules/.pnpm/@auth0+nextjs-auth0@3.1.0_next@13.4.16/node_modules/@auth0/nextjs-auth0/dist/handlers/callback.js:71:16
      at async /Users/jamessherry/sites/new-jump/student-portal-next-sanity/node_modules/.pnpm/@auth0+nextjs-auth0@3.1.0_next@13.4.16/node_modules/@auth0/nextjs-auth0/dist/handlers/auth.js:79:13 {
    status: 400,
    statusCode: 400
  },
  status: 400
}

Any help GREATLY appreciated!!

EDIT: Just to note that this is what happens locally. The code works remotely (for the moment)
FURTHER EDIT: No state cookie is ever set. state does appear as a URL parameter though

3 Likes

Have you had any luck? I am facing the same error and it is driving me crazy.

Same issue here! I deleted the cookies manually, and then never got them back again on my response:

    login: async (req: any, res: any) => {
        try {

            const result = await auth0.handleLogin(req, res, {
                authorizationParams: {
                    prompt: 'login',
                },
            });

            console.log("RESULT", result);

            return result
        }
        catch (error) {
            console.error("login error: ", error);
            return res.status(500).send({ error: 'An error occurred during login' });
        }
    },

that log doesn’t return the cookies, and my partner gets the cookies on the same log. I have tried everything without success.

@juanzuluagag and @diego2 : This issue was with a node version and Next.js 13’s behaviour. The node version was 18.2.. If you upgrade your node and next versions you should find the problem goes away.

1 Like

Thank you very much for your answer. Could you please confirm the current versions you are using for node and for next.js?

Sure, I’m using node: v18.17.1 and next.js ^13.4.19

Was there ever a root cause identified here? All of my applications decided to just stop working out of the blue. Logins succeed via auth0 monitoring. /callback endpoint errors 400 with the same error listed above. The application i’m currently developing works locally both built and non-built version (dev server) but not deployed via vercel. I’ve tried switching node version from v18.18.2 to v20.10.0 and still no luck. Locally the appSession cookie is set, deployed versions do not get appSession cookie post login.

Next.js version: 13.5.6

Any ideas?

Hi,

This helped me: Cypress login on page with withPageAuthRequired fails with "Missing state cookie from login request" error · Issue #1392 · auth0/nextjs-auth0 · GitHub

I added the following AUTH0_TRANSACTION_COOKIE_SAME_SITE=none to my .env file and it fixed my issue.

Hope it works for you.

1 Like

Thanks for the reply! Unfortunately i wasn’t able to test this as my apps happened to all be working this morning when i woke up. This was a good lead and I’ll continue to review and dig into it as I’m not confident that the issue is resolved. Based on the contributors comment doesn’t look like i should set AUTH0_TRANSACTION_COOKIE_SAME_SITE=none for my production apps as i need https. Not sure if you know more about what exactly this flag does, any additional info would be greatly appreciated.

Per the below linked docs “none: Send the cookie with requests crossing the website origin bounds. Unless other conditions are present (i.e., third-party cookies are blocked), do not send the cookie.” - to my understanding auth0 provides the data needed to for nextjs-auth0 to set the cookie on the same domain so not sure why this would fix the issue. Please correct me if i’m wrong.

Hello everyone. Any updates about this?

I deployed nextjs ^14.0.2 to vercel.
Everything worked fine then after a few hours I got same error.

As I remember I didn’t logout. Could the cause of this error be an expired token?

I’ve identified the issue in my case. Both localhost and production work fine, but the preview doesn’t because it changes the URL with every new deployment. This new URL is not registered in the Auth0 dashboard.

As the error indicates, double-checking the URL was the key to resolving the issue.