sveltejs / sveltejs/kit

Credentials example in handleFetch hook documentation is incorrect if a cookie was set by SvelteKit

Open
#7,705 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

  • #16097 by @starkmarkus — closed without merging
documentation
Dominant language
JavaScript
Stars
20.8k
Forks
2.3k
Avg merge
1d 16h
Merged PRs (30d)
156

Description

Describe the bug

The documentation for handleFetch provides the following example for forwarding cookies to an API on a different domain than SvelteKit is hosted at:

/** @type {import('@sveltejs/kit').[HandleFetch](https://kit.svelte.dev/docs/types#sveltejs-kit-handlefetch)} */
export async function handleFetch({ request, fetch }) {
  if (request.url.startsWith('https://api.yourapp.com/')) {
    // clone the original request, but change the URL
    request = new Request(
      request.url.replace('https://api.yourapp.com/', 'http://localhost:9999/'),
      request
    );
  }
 
  return fetch(request);
}

Based on that, I created the following hook to additionally forward cookies from the API server to the client (since it appears that cookies are not forwarded on their own):

import envariant from '@knpwrs/envariant';
import type { HandleFetch } from '@sveltejs/kit';

const GRAPHQL_URL = envariant('GRAPHQL_URL');
const COOKIE_KEY = 'lcSessionId';

export const handleFetch: HandleFetch = async ({ event, request, fetch }) => {
  const cookie = event.request.headers.get('cookie');

  if (request.url.startsWith(GRAPHQL_URL) && cookie) {
    request.headers.set('cookie', cookie);
  }

  const res = await fetch(request);

  const cookieValue = res.headers
    .get('set-cookie')
    ?.replace(`${COOKIE_KEY}=`, '');

  if (cookieValue) {
    event.cookies.set(COOKIE_KEY, cookieValue, {
      sameSite: 'lax',
      httpOnly: true,
      path: '/',
    });
  }

  return res;
};

The issue is that it appears that SvelteKit is URL-encoding the cookie value with event.cookies.set, but then not URL-decoding the cookie value when reading event.request.headers.get('cookie'). This makes sense as they're different APIs, but it leads to unintuitive bugs where a cookie set by SvelteKit is ultimately not sent to backend APIs in the same form it was set.

Reproduction
  1. Set a cookie with
  2. Attempt to forward that cookie using provided example in the documentation
Logs

No response

System Info
System:
    OS: macOS 12.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 82.08 MB / 32.00 GB
    Shell: 5.8 - /opt/homebrew/bin/zsh
  Binaries:
    Node: 18.10.0 - /nix/store/m3za3mblwg9az7vpkkvlfm04z66mcr6y-nodejs-18.10.0/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 8.19.2 - /nix/store/m3za3mblwg9az7vpkkvlfm04z66mcr6y-nodejs-18.10.0/bin/npm
    Watchman: 2022.10.03.00 - /opt/homebrew/bin/watchman
  Browsers:
    Brave Browser: 106.1.44.101
    Chrome: 107.0.5304.110
    Chrome Canary: 99.0.4828.0
    Firefox: 106.0.5
    Safari: 15.2
  npmPackages:
    @sveltejs/adapter-auto: ^1.0.0-next.88 => 1.0.0-next.88 
    @sveltejs/kit: ^1.0.0-next.548 => 1.0.0-next.548 
    svelte: ^3.53.1 => 3.53.1 
    vite: ^3.1.0 => 3.2.4
Severity

annoyance

Additional Information

IIRC it isn't possible to set the set-cookie header in SvelteKit. Maybe it should be possible to set this header in hooks but not in page/layout handlers? That way backend cookies can be forwarded directly.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the handleFetch server-hooks documentation and the cookie APIs shown in the report. Reproduce the interaction between event.cookies.set, request cookie headers, and set-cookie forwarding, then determine the documented behavior or API change needed so cookies are forwarded consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
api, documentation
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.