Skip to content

fix: use getSetCookie() to preserve multiple Set-Cookie headers in middleware#1191

Open
jdnurmi wants to merge 2 commits into
opennextjs:mainfrom
jdnurmi:fix/middleware-set-cookie-folding
Open

fix: use getSetCookie() to preserve multiple Set-Cookie headers in middleware#1191
jdnurmi wants to merge 2 commits into
opennextjs:mainfrom
jdnurmi:fix/middleware-set-cookie-folding

Conversation

@jdnurmi

@jdnurmi jdnurmi commented Jun 25, 2026

Copy link
Copy Markdown

Problem

Terminal-return middleware responses with multiple Set-Cookie headers get folded into a single comma-joined value. The browser receives one corrupt cookie; multi-cookie sessions are dropped.

Triggered by any auth library that chunks a large session across multiple cookies (e.g. @auth0/nextjs-auth0 v4 sets appSession.0/1/2 on the /auth/callback redirect). The session never persists; the callback returns a 500 with no app logs.

Root cause

Headers.forEach folds same-name headers per the WHATWG spec. Both harvest sites accumulate set-cookie through forEach:

responseHeaders.forEach((value, key) => {
  if (key.toLowerCase() === "set-cookie") {
    resHeaders[key] = resHeaders[key] ? [...resHeaders[key], value] : [value];
  }
});

When folding occurs, value is already "appSession.0=…, appSession.1=…, appSession.2=…" — one string. Result: one corrupt Set-Cookie entry instead of three.

Affected:

  • core/routing/middleware.ts (~L127) — terminal-return and rewrite paths
  • adapters/edge-adapter.ts (~L48)

getSetCookie() is not called anywhere in the codebase prior to this PR.

Fix

Skip set-cookie in forEach, call getSetCookie() after. getSetCookie() stores cookies discretely and always returns a proper string[].

Tests

New tests use a simulated folding Headers object (forEach yields pre-joined string, getSetCookie returns them split) to be runtime-independent. Confirmed to fail on unpatched code:

AssertionError: expected [ Array(1) ] to deeply equal [ …(3) ]

Related

…ddleware

Headers.forEach folds same-name headers per WHATWG. Both harvest sites
accumulate set-cookie through forEach, which yields one pre-joined string
on runtimes where folding occurs — breaking any terminal-return response
that sets multiple cookies (e.g. chunked auth sessions).

Replace with getSetCookie() at:
  - core/routing/middleware.ts  (terminal-return and rewrite paths)
  - adapters/edge-adapter.ts

Adds regression tests using a simulated folding Headers object, confirmed
to fail on unpatched code and pass with the fix.
@pkg-pr-new

pkg-pr-new Bot commented Jun 25, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@opennextjs/aws@1191

commit: 03ce47c

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 26, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 70a7119

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@jdnurmi

jdnurmi commented Jun 26, 2026

Copy link
Copy Markdown
Author

(updated for style)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant