next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Encode isn't an option in Cookie

Open c0d3rm0n opened this issue 1 year ago • 4 comments

Link to the code that reproduces this issue

https://github.com/c0d3rm0n/test-set-cookies

To Reproduce

I'm creating an app that uses third party libraries that use Go and set / send their cookies in raw format, and they expect to receive them in the same format.

I use those services in my server actions, and then I have to set the cookies they send inside of response headers. As result of this action, the cookie(s) sent to my server will be set in my browser.

However, the function cookies().set({...my_cookie}) from next/headers will encode the cookie and the value set will not match the original one, causing my calls to those 3rd party libs to fail or give error.

From what I could find, encode should be an option of Cookie, and in next.js modules it is possible to find an interface that includes it (CookieSerializeOptions) but then, the other interfaces that use it don't include encode... So, even if I try to set a cookie like cookies().set({...my_cookie, encode: String}) the browser record will be encoded.

The same happens in Middleware, using nextResponse.cookies.set({...my_cookie}).

Current vs. Expected behavior

I would like to be able to set a cookie and define the encoding function in it's options.

For example, the function cookies().set({...my_cookie, encode: String}) should accept encode as option and save a value like qwerty123= and not qwerty123%3D as it is saving at the moment...

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
Binaries:
  Node: 20.11.0
  npm: 10.2.4
Relevant Packages:
  next: 14.1.4
  eslint-config-next: 14.1.4
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.4.4
Next.js Config:
  output: standalone

Which area(s) are affected? (Select all that apply)

Middleware / Edge (API routes, runtime)

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

No response

c0d3rm0n avatar Apr 11 '24 14:04 c0d3rm0n

Yeah, I'm having the same error in my codebase. Lost hours. For now I'm returing them from server action and setting them in client component with document.cookie=.....

xluk9 avatar Apr 15 '24 18:04 xluk9

I ended up creating route handlers (API) so I can serialize the cookies and set them in my response header. This should be possible to do in server actions as one of its intent is to create a shortcut for server handlers instead of creating API routes. For me it is a bit disappointing to create these route handlers to deal with some form submits instead of making all of my 3rd party calls by server actions... I really think that it should be possible to set the encode function as a cookie option. If you want to use something different from the default encode method, why not do it if it is an option that is referred in cookie standard?

c0d3rm0n avatar Apr 16 '24 10:04 c0d3rm0n

Same issue here, would be useful to have a way to specify custom "encode" function whenever we don't want to use encodeURIComponent which is default one.

ejasarevic avatar Jun 03 '24 15:06 ejasarevic

We're looking into this particular use case now. It may be possible to modify the encode property in the future for the cookies().set(). We're investigating this now.


Bear in mind that RFC2109 requires that the cookie value either be a:

  1. quoted-string (see RFC2109#4.1):
          quoted-string  = ( <"> *(qdtext) <"> )

          qdtext         = <any TEXT except <">>
  1. token (see RFC2068#2.2):
          token          = 1*<any CHAR except CTLs or tspecials>

          tspecials      = "(" | ")" | "<" | ">" | "@"
                         | "," | ";" | ":" | "\" | <">
                         | "/" | "[" | "]" | "?" | "="
                         | "{" | "}" | SP | HT

This would mean that if the user sets a cookie via cookies().set(), and specifies a encode: String option, they must quote the string if it contains special characters like =. If these aren't encoded according to the spec, then the risk of other parsers not correctly handling the cookie parsing logic is high.

wyattjoh avatar Jul 04 '24 00:07 wyattjoh

@wyattjoh any updates on this? We're having to create an api route to set cookies for a client because their backend doesn't decode the cookie string before ingesting.

Frustrating and I'm hoping to get them to update their code but if the cookies().set() method would allow us to override the encoding that would be super helpful

Thanks!

DrewLandgraveCbsi avatar Jul 30 '24 13:07 DrewLandgraveCbsi

I was able to work around this issue by manually appending the Set-Cookie header instead of using response.cookies.set(), but I agree that exposing the encode function would be ideal

response.headers.append(
          "Set-Cookie",
          `${cookie.name}=${cookie.value}; Path=/; HttpOnly; Secure; SameSite=None;`,
        );

See mdn docs for more info

aaronzhongg avatar Aug 26 '24 02:08 aaronzhongg

Docs say it's available now https://nextjs.org/docs/app/api-reference/functions/cookies

However the types for 15.0.3 don't. Screenshot 2024-12-02 at 3 25 50 PM

DrewLandgraveCbsi avatar Dec 02 '24 20:12 DrewLandgraveCbsi

Taking a quick glance it seems this is not implemented yet for the edge runtime. Within @edge-runtime/cookies v6.0.0 used by Next.js 15.1.0 it is always calling encodeURIComponent. I haven't looked at other runtimes so maybe those have it implemented.

https://github.com/vercel/edge-runtime/blob/440c123a37284d6a852ce453af810ad484ecfc01/packages/cookies/src/serialize.ts#L21

Juuldamen avatar Dec 13 '24 17:12 Juuldamen

Hello everyone, I have the same problem. When trying to add cookies received from my backend using the .set() function, it is impossible to set the 'encode' parameter to modify the encoding function. Yet, it is specified as a parameter in the Next.js documentation.

I am using the function in server actions.

corentin-hannoye avatar Feb 28 '25 23:02 corentin-hannoye

Hi there, I also have the issue. Would be nice to have that issue resolved soon. I am also using the cookies().set() method inside a server action.

noxnx avatar Jul 03 '25 12:07 noxnx

Same here, it's a shame that this is forced upon us; currently working on an integration with an older app, which is half the point of using cookies in the first place. Older app is legacy, I don't want to change it, so I have to hackfix it with this set-cookie header stuff. Not ideal. Indeed this other app does break the RFC's rules, but there should still be some way of disabling this... right?

explaingarlic avatar Jul 29 '25 10:07 explaingarlic

This is very annoying, cannot use server actions in our application because of this. We have external systems which won't work if the session cookie all of a sudden get's url encoded. And the only way to update the cookies in a server action is to use the url-encoding cookies().set() method 😢

lisarutan avatar Aug 14 '25 10:08 lisarutan