Callback handler fail 400 Bad request with NextJS

Problem statement

After a successful login with the Next.js SDK, when redirected to the callback route /api/auth/callback, a 400 Bad Response error occurs.

Symptoms

  1. The /api/auth/callback is showing a Chrome error “net::ERR_HTTP_RESPONSE_CODE_FAILURE” a few milliseconds after, so a timeout is discarded.
  2. LoginHandlerError: Login handler failed.
  3. CallbackHandlerError: Callback handler failed.
  4. 400 Bad request

Steps to reproduce

  1. Go to the unauthenticated page
  2. Login

Troubleshooting

Check if the error occurs locally or not. If it works when running the app locally there may be a cache setting where the app is hosted that is disrupting the login flow.

Cause

Many hosting providers will offer to cache content at the edge to serve data to users as fast as possible. For example, Vercel will cache content on the Vercel Edge Network for all static content and Serverless Functions if provided the necessary caching headers in the response.

It is not recommended to cache any response that requires authentication. Even if the response’s content appears safe to cache, there may be other data in the response that isn’t.

The Next.js SDK offers a rolling session by default, which means that any response that reads the session will have a Set-Cookie header to update the cookie’s expiry. Vercel and potentially other hosting providers include the Set-Cookie header in the cached response, so even if the response’s content can be cached publicly, the response Set-Cookie header cannot.

A har file may indicate that cached data is being served in the response to the callback handler. For example, with Cloudfront, if the X-Cache header is “Hit from Cloudfront” or “RefreshHit from Cloudfront,” then the request was served from the cache of the edge location.

Solution

Check the hosting provider’s caching rules, but in general, never cache responses that either require authentication or even touch the session to check authentication (e.g., when using withApiAuthRequired, withPageAuthRequired or even just getSession or getAccessToken ).

With Cloudfront, it may be necessary to add the “auth_verification” cookie to an allowlist.