ciscoheat/sveltekit-flash-message

Flash message conflicts with hooks.server.js

gmag95 opened this issue · 5 comments

I am building a webapp using pocketbase as a login database but i am having problems passing the flash message after an authentication request. After some tests the problem looks related to the hooks.server.js file: if i remove it the message is displayed correctly otherwise the flash message does not appear. These are my current files:

hooks.server.js

import { pool } from '$lib/server/db/config.js';
import PocketBase from 'pocketbase';

export const handle = async ({event, resolve}) => {
    event.locals.pool = pool;
    event.locals.pb = new PocketBase("http://127.0.0.1:8090");
    event.locals.pb.authStore.loadFromCookie(event.request.headers.get('cookie') || '');
    
    if (event.locals.pb.authStore.isValid) {
        event.locals.user = structuredClone(event.locals.pb.authStore.model)
    } else {
        event.locals.user = undefined;
    }

    const response = await resolve(event);

    response.headers.set('set-cookie', event.locals.pb.authStore.exportToCookie({secure: false}));
    return response;
}

+layout.server.js

import { loadFlashMessage } from 'sveltekit-flash-message/server';

export const load = loadFlashMessage(async ({locals}) => {

    if (locals.user) {
        return {
            user: locals.user
        }
    } else {
        return {
            user: undefined
        }
    }
})

/auth/+page.server.js (the authentication endpoint)

import { redirect } from 'sveltekit-flash-message/server'

export const actions = {
    login: async (event) => {

        const origin_url = event.request.headers.get('referer');

        const login_body = Object.fromEntries(await event.request.formData());

        try {

            await event.locals.pb.collection('users').authWithPassword(login_body.email, login_body.password);

        } catch(e) {
            console.log(e.data);
        }

        const message = { type: 'success', message: 'Endpoint POST successful!' };

        throw redirect(303, origin_url, message, event)
    }}

+layout.svelte

<script>
    import { initFlash } from 'sveltekit-flash-message/client';
    import { page } from '$app/stores';
  
    const flash = initFlash(page);
</script>

{#if $flash}
    <div>{$flash.message}</div>
{/if}

What can i do to have both the hooks file (required for the authentication process) and show a flash message afterwards?

Hi, on the top of my head, it looks like the flash cookie goes missing in the cookie manipulation that is done in hooks.server.js.

Can you use event.cookies to get and set the authorization cookie, and see if that makes any difference? If it doesn't, let me know and I'll make some further tests.

You can use console.log(event.cookies.get('flash')); to see if it's present in the hooks file, of it it doesn't even get there.

I followed your suggestions and found out that the problem was caused by this line of code that overwrites the cookie used by your library:

response.headers.set('set-cookie', event.locals.pb.authStore.exportToCookie({secure: false}));

The solution that i found was to change set with append, like this:

response.headers.append('set-cookie', event.locals.pb.authStore.exportToCookie({secure: false}));

This way both the authentication and the flash cookies are passed to the page and everything works as intended. Thank you very much for your support and the creation of this library!

Issue closed

Glad that it was an easy fix, and thanks for using the library! :)