Skip to content

fix(rsc): include cookies in RSC navigation and prefetch requests#123

Merged
FredKSchott merged 1 commit intocloudflare:mainfrom
SeolJaeHyeok:fix/rsc-navigation-credentials
Feb 27, 2026
Merged

fix(rsc): include cookies in RSC navigation and prefetch requests#123
FredKSchott merged 1 commit intocloudflare:mainfrom
SeolJaeHyeok:fix/rsc-navigation-credentials

Conversation

@SeolJaeHyeok
Copy link
Copy Markdown
Contributor

Summary

RSC navigation and prefetch requests were missing credentials: 'include',
causing browsers to silently omit cookies from these requests. This broke
cookie-based authentication (Better Auth, NextAuth, etc.) during client-side
navigation.

Root cause: A full-page reload works correctly — the browser always sends
cookies with HTML navigation requests. But when a user clicks a <Link>, vinext
fetches the RSC payload via fetch(), and without credentials: 'include' the
browser omits all cookies from the request. The server receives no session cookie
and authentication fails.

Three call sites fixed:

File Context
server/app-dev-server.ts __VINEXT_RSC_NAVIGATE__ — actual navigation fetch
shims/link.tsx <Link> prefetch triggered on viewport intersection
shims/navigation.ts router.prefetch() programmatic prefetch
- navResponse = await fetch(rscUrl, {
-   headers: { Accept: "text/x-component" },
- });
+ navResponse = await fetch(rscUrl, {
+   headers: { Accept: "text/x-component" },
+   credentials: "include",
+ });

Reproduction

  1. Set up cookie-based auth (e.g., Better Auth or NextAuth)
  2. Have a protected route that calls cookies() on the server
  3. Navigate to a public page, then click a to the protected route
  4. Before: Auth fails — session cookie not sent with the RSC fetch
  5. After: Auth succeeds — cookies included in all RSC requests

A full page refresh on the protected route always worked correctly. Only
client-side navigation was affected.

Notes

  • credentials: 'include' is the correct choice here: RSC fetches are always
    same-origin (they go to the same vinext dev server / production host), so this
    cannot cause credential leakage to third parties. Rewrites to external origins
    are handled by the server-side proxy which already strips cookies before
    forwarding.
  • Prefetch requests with stale/unauthorised responses are discarded when
    consumed — no change to that logic.

Fixes #85

RSC navigation and prefetch fetches were missing ,
causing browsers to omit cookies from these requests. This silently broke
cookie-based authentication (Better Auth, NextAuth, etc.) during client-side
navigation: a full-page load would succeed (cookies sent normally) but any
subsequent <Link> navigation to a protected route would fail authentication
because the RSC fetch arrived without the session cookie.

Three fetch call sites are fixed:
- server/app-dev-server.ts — __VINEXT_RSC_NAVIGATE__ navigation fetch
- shims/link.tsx            — <Link> prefetch on viewport intersection
- shims/navigation.ts      — router.prefetch() call
@FredKSchott
Copy link
Copy Markdown
Collaborator

FredKSchott commented Feb 27, 2026

Thanks @SeolJaeHyeok! Pushed a commit that changes credentials: "include"credentials: "same-origin" and adds the option to 3 additional fetch calls that were missing it (server action POST, fallback RSC hydration, HMR re-render).

Why same-origin instead of include: Next.js uses credentials: 'same-origin' for all RSC fetch calls — see createFetch() in fetch-server-response.ts. The comment there explains it's for backward compat with older browsers where same-origin wasn't yet the default. Since all our RSC fetches are same-origin (relative URLs via toRscUrl()), same-origin gives the same cookie-sending behavior while being safer — include would leak cookies if a cross-origin RSC fetch path were ever introduced.

@FredKSchott FredKSchott enabled auto-merge (squash) February 27, 2026 06:21
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Feb 27, 2026

Open in StackBlitz

npm i https://pkg.pr.new/vinext@123

commit: d60883f

@FredKSchott FredKSchott merged commit 1b5ecf7 into cloudflare:main Feb 27, 2026
20 checks passed
southpolesteve added a commit that referenced this pull request Feb 27, 2026
Co-authored-by: ask-bonk[bot] <ask-bonk[bot]@users.noreply.github.com>
Co-authored-by: southpolesteve <southpolesteve@users.noreply.github.com>
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.

RSC navigation fetch missing credentials: 'include' - cookies not sent during client-side navigation

2 participants