Table of Contents

SvelteKit auth with seperate Backend

SvelteKit auth with seperate Backend

Handle fetch to other backend and forward cookie

src/hooks.server.ts

export const handle = async ({ event, resolve }) => {
	const res = await event.fetch(`http://127.0.0.1:3000/user`);
	if (res.ok) {
		const data = await res.json();
		event.locals.user = data;
	}

	const response = await resolve(event);
	return response;
};

export const handleFetch = async ({ event, request, fetch }) => {
	if (request.url.startsWith('http://127.0.0.1:3000/')) {
		// forward cookies to API
		const cookies = event.request.headers.get('cookie');
		if (cookies) request.headers.set('cookie', cookies);

		const fetchResponse = await fetch(request);

		// Set cookies from API response
		if (fetchResponse.ok) {
			const setCookie = fetchResponse.headers.get('set-cookie');
			if (setCookie) {
				Object.entries(parseCookie(setCookie)).forEach(([name, value]) => {
					event.cookies.set(name, value, { path: '/', httpOnly: true });
				});
			}
		}

		return fetchResponse;
	}
	return fetch(request);
};


function parseCookie(str: string): { [key: string]: string } {
	const cookieParts = Array.isArray(str) ? str : str.split(/,(?=\s*[A-Za-z0-9_\-]+=)/);

	const cookies: { [key: string]: string } = {};
	cookieParts.forEach((cookieStr) => {
		const [nameValue] = cookieStr.split(';');
		const [name, ...valParts] = nameValue.split('=');
		cookies[decodeURIComponent(name.trim())] = decodeURIComponent(valParts.join('=').trim());
	});

	return cookies;
};

Define locals

src/app.d.ts

declare global {
	namespace App {
		interface Locals {
			user?: {
				name: string;
			};
		}
	}
}

export {};

Return user data to page

src/routes/+page.svelte

export const load = async ({ locals }) => {
	return {
		user: locals.user
	};
};

Login and show user data

src/routes/login/+page.svelte

<script>
	import { enhance } from '$app/forms';
	import { page } from '$app/state';
</script>

{#if page.data.user}
	<p>Hello {page.data.user.name}</p>
{:else}
	<form method="POST" action="?/login" use:enhance>
		<button>Login</button>
	</form>
{/if}
export const actions = {
	login: async ({ fetch, cookies }) => {
		await fetch(`http://127.0.0.1:3000/login`, { method: 'POST' });
	},

};