Search code examples
cookiessveltekit

Cookie not set when calling API from Sveltekit server action


I have a simple ASP.NET API which exposes a login endpoint that returns a session cookie upon succesful authentication. As expected, when I call this API from the client side (Sveltekit application) I receive the cookie and everything works as expected:

// +page.svelte
<script>
    const handleSubmit = async (event) => {
        await fetch("http://localhost:5052/auth/login", {
            method: 'POST',
            credentials: 'include',
        })
    }
</script>

<form method="POST" on:submit|preventDefault={handleSubmit}>
...
</form>

Submitting the form sends the request and returns the cookie: cookie

The problem occurs when I try to call this login API from a Sveltekit form action:

// +page.svelte
<script>
    import { enhance } from '$app/forms';
<script>

<form method="POST" use:enhance>
...
</form>

// +page.server.ts
import type { Actions } from "./$types";

export const actions = {
    default: async ({ fetch, request }) => {
        await fetch("http://localhost:5052/auth/login", {
            method: 'POST',
            credentials: 'include',
        })
    }
} satisfies Actions;

The response from the server action does not contain any Set-Cookie header and the client will not receive any cookies. Could somebody tell me what I'm missing here?


Solution

  • The request is being processed in the SvelteKit server, so the browser never gets the cookie. There are probably various valid options:

    • Forward the response directly via a +server.ts endpoint
    • Forward it via a hook
    • Process the response and set cookies in the form action (form actions do not return full Response objects, so you cannot just forward the response)

    For the last option, it would look something like this:

    export const actions = {
        default: async ({ fetch, cookies }) => {
            const response = await fetch("http://localhost:5052/auth/login", {
                method: 'POST',
                credentials: 'include',
            });
    
            // [error handling here]
    
            const cookie = response.headers.get('set-cookie');
            const token = getCookieToken(cookie); // [implement this]
            cookies.set('session_id', token);
        }
    } satisfies Actions;