Setup
I have a typical web app setup:
- A backend service running at
https://mybackendsvc.com - Users are authenticated with
mybackendsvc.com, and have a session cookie. - Svelte/Sapper running at
https://myfrontend.com
I'm using Sapper preload to fetch some data from https://mybackendsvc.com. Here's routes/mydata/[id].svelte:
<script context="module">
export async function preload(page, session) {
const res = await this.fetch(
`https://mybackendsvc.com/api/public/${page.params.id}`,
{
credentials: 'include' // sends the session cookie to mybackendsvc.com
}
);
if (res.status == 200) {
let myData = await res.json();
return { myData };
} else if (res.status === 401) {
this.error(401, "Unauthorized");
} else {
this.error(500, "Something went wrong");
}
}
</script>
<script>
export let myData;
</script>
<div>
{myData}
</div>
Note the use of fetch with credentials included:
{
credentials: 'include'
}
The problem: Where "preload" executes matters
If a user navigates to mydata/[id] directly, preload runs on the node server, Sapper doesn't include the user's session cookie (likely because the node server doesn't have access to it), so mybackendsvc.com responds with 401. However if a user navigates to mydata/[id] via a link inside my app, preload is run browser-side, the browser includes the session cookie, and the call succeeds.
How can I make Sapper guarantee that fetch includes credentials in an api call? Or can you not use preload with authenticated API calls, only public API calls?