-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make server version of fetch() in load() copy over 'set-cookie' to the page response #1198
Comments
Hmm, just realize this requires merging 'set-cookie' if there are multiple Feel free to close this issue if this doesn't seem worth it. |
Simple experimentation with default configurations shows that multiple same-origin cookies make it to the client even when SSR'd, which makes sense. This situation you're describing seems to only occur with either:
If neither of these describe your situation, please elaborate. |
Hmm, here are my findings after experimenting with a small test case:
When you open
If I change
It seems this only works if you throw away |
Another issue with setting the cookie with client js is that, because you probably want to redirect to the login page, it can prevent the current page from being returned to the browser, so the client js doesn't have the chance to make that API call to create the session: <script context="module">
export async function load({ fetch }) {
await fetch("/session");
return {
status: 302,
redirect: '...',
};
}
</script> |
Related issue: #842 |
I'm experiencing this with The workaround I'm using is to just call EDIT: Create a reproduction repo: https://github.com/benwoodward/sveltekit-headers-issue-demo |
Some places to look for anyone who'd want to implement this:
https://github.com/node-fetch/node-fetch#extract-set-cookie-header |
Hey all, turns out that the problem I was running into (see my comment in #1777) was exactly this problem: I am doing the server request to login during SSR, and so the set-cookie header in the response basically had no effect. Adding I noticed in the changelog that this problem should be fixed in version 166, but that's not actually released yet. Any word on a timeline? |
we ran into some hiccups, but 166 should be released now |
@benmccann I believe this is still broken when trying to set multiple cookies in load. In my endpoint, I'm setting 2 cookies as detailed in the docs:
However, only cookie1 is set in the browser. If I change the code to:
Only cookie2 is set in the browser. I'm more than happy to throw together/link to a simple reproduction repo if that would help! |
Yes, a reproduction repo would help get this looked at much faster. Thanks!! |
Reproduction repo: https://github.com/cryptodeal/load-multiple-cookies Further testing while throwing together a super basic repo to reproduce the bug provided a bit more insight:
For context, I first encountered this issue when building out a DIY magic link auth system. I use nodemailer to send the authToken verification link to the user's email; the verification/[authToken].json.js endpoint attempts to set both an accessToken and a refreshToken, but the browser only stores the first cookie for whatever reason. (tested in Brave Browser, Chrome, and Safari). |
I'v met same problem. It seems we should split multiple cookies from one string #2362 (comment). |
The big question I'd have for the other maintainers is do we want to add another dependency to deal with this (e.g. |
Just curious as to why the SvelteKit behavior is different from Sapper's in regards requiring the same or more specific subdomain in server side fetch requests, versus just having the same domain. Currently I have two Sapper apps, one for the frontend public site at (www.example.com) and one for our backend admin panel (admin.example.com). They both communicate with our API at api.example.com. I started migrating our admin panel to SvelteKit, but had to create a proxy domain (api.admin.example.com) for server side request to pass authentication cookies. Requests made from the browser worked just fine with api.example.com. Is this the intended way that SvelteKit will be going forward? Or is this just a temporary issue? |
When I was working on my SvelteKit app and Django-based API locally, everything worked fine. When the web app logs in on the API, the API sends back a set-cookie header with the // hooks.js
import cookie from "cookie";
export async function handle({ request, resolve }) {
const cookies = cookie.parse(request.headers.cookie || "");
request.locals.token = cookies.token;
return await resolve(request);
}
export function getSession({ locals }) {
return {
token: locals.token,
};
} And on every request that's made to the API server from then on, the cookie containing the token would be sent back, and all was well. Now I have deployed my project, and I am running into a problem. When www.example.com logs in to the API at api.example.com, the cookie is set with the I guess I could set the cookie domain to |
So now the question is: do I wait for this bug to be fixed, or do I go with my workaround that does need a pretty big refactor. Is this something that's currently on the radar of the SvelteKit team, or would you advice me to not hold my breath? Which is a perfectly valid answer of course, not everything has the highest priority :) |
Guys, I am completely stuck due to this issue, and it's causing serious problems in my website. I'm starting to panic a little bit :( So I have a SvelteKit website www.example.com, and an external API at api.example.com. What I want to do:
On localhost this all works fine (where both the website and the API are running on localhost, cookie domain is localhost as well). However, on the production website and API the cookie is never stored, and thus you're never logged in! My temporary fix right now is to just set a cookie client-side: the server returns the token in the body, and I simply store it in a client side cookie. From there hooks.js puts it in $session, it gets sent back to the API on every request, that part is the same. This workaround does work, but with one huge problem: the maximum age of the cookie is horrible, at least in Safari. Users are now logged out after 24, they have to re-login every single day! I really need the HttpOnly cookies to work, and I can't figure out why they are not set in my production environment. I've tried setting the domain to example.com and to www.example.com, I've tried samesite strict and lax, secure true and false, I've tried turning off SSR in SvelteKit, but no matter what, I just don't get the HttpOnly only cookies to stick around. Can anyone please help? |
I think what might be happening is that the host is not being forwarded on your live server. If you're hosting on Netlify, Vercel, GCP, etc, the actual host domain is not example.com, so the cookie is not being sent with the request. You can log the host in production to make sure. Svelte kit has an property called |
I'm hosting this on my own VPS, and yeah there are definitely no other domains involved. |
@kevinrenskers I'm wondering whether this issue has something to do with the fact that the cookie is coming from a different domain (because the API is on a subdomain). Have you tried serving the cookie from an endpoint that is reachable via a subdirectory URL, e.g. example.com/api/session ..? Or is that not a feasible solution? |
api.example.com should be able to set a cookie for either example.com or even www.example.com just fine, normally speaking. Right? Calling my external API via an endpoint could be a solution 🤔 I don't think that's how SvelteKit should deal with HttpOnly cookies though? |
Agree. But I think it's worth testing because it's possible you've discovered an edge-case there's a separate bug involved. |
Ok, that works. I am now calling my external login endpoint via a SvelteKit endpoint, where I am setting a HttpOnly cookie. I can now login correctly, and stay logged in for more than a day 😅 |
I recommend submitting a separate issue for this, it's maybe a bug. Even if it's not the issue itself is useful for other people stuck on the same problem. |
hi @kevinrenskers to clarify, your workaround here is by making the API calls from |
Correct. The Django backend doesn't deal with cookies anymore, I removed all of that. So the Django login endpoint simply returns a token in the body, and all other endpoints check for a token in the headers. No more setting and reading cookies in the Django API. To clarify though, ONLY the login endpoint goes via a SvelteKit endpoint, all other requests are made directly to the Django endpoint. You could route all requests through a SvelteKit endpoint but I didn't want to be making so many extra requests. |
ah... i was afraid i had to resort to that.. thanks for clarifying. |
Feels like this is getting out of topic already so I apologize in advance to the maintainers for adding noise to the issue tracker... but how are you doing this again? if you're checking for a token in the header anyway, how are you getting the token to set the value? and why do you even need the httponly cookie? |
https://www.loopwerk.io/articles/2021/sveltekit-cookies-tokens/ If you have more question, probably better to just contact me directly :) |
Worked fine until
|
Try changing it to |
Hi, I'm having the exact same issue. Is this currently being addressed or is it intended behavior? |
fix: Workaround for sveltejs/kit#1198
* apply set-cookie headers from page dependencies - fixes #1198 * hmmm * deps * accommodate commonjs laggards * Update packages/adapter-static/package.json Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com> * fix lockfile Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
Is your feature request related to a problem? Please describe.
Currently, the isomorphism of the
load()
function breaks when afetch
response, from an internal url, containsset-cookie
. If it's called by the client, the cookie is set in the browser, if it's called by the server, the cookie is dropped.One use case is to create a session when a guest visits a page that should only be visible to a registered user. This session should record what page to return the guest to, once she registers.
Some people might suggest passing the return url as a query to the register page, but that means we now have to sanitize the url, prevent users from being redirected to external sites, and even if we do this, we still can't prevent users from being redirected to other irrelevant internal pages (e.g., people register via an url shared online that contains the query to redirect them to an irrelevant page)
Describe the solution you'd like
The server's version of
fetch
should copy over cookie headers from the fetch response, from an internal url, to the page response, (including a redirect response like 302)Describe alternatives you've considered
We can redirect guests to an endpoint that creates the session and return the cookie header, but that forces a page refresh, breaking the SPA experience that svelte kit tries so hard to deliver.
How important is this feature to you?
Very, and I think this recording return url use case should be really common.
Additional context
None.
The text was updated successfully, but these errors were encountered: