I attempting to create a SvelteKit application, and I think I am misunderstanding the use of fetch
and hooks
. When I have a login page, and in the form actions I am able to decode a jwt
and add it to the cookies, however, it seems that if I make a request from inside of a <script>
tag that those cookies are not a part of the request, meaning that I am not authenticated to my rest framework backend when I use fetch()
inside of a <script>
After reading the SvelteKit docs, and about "not importing sensitive information" into the frontend client, I am having difficulty understanding these things:
- If it is possible to have a fetch in the frontend that passes a token from cookies to headers somehow and also
- Is this the intended use for fetch in SvelteKit?
- What is the use for hooks.server.ts?
- Am I setting cookies correctly?
src/routes/+page.server.ts
import { type Actions, type ServerLoad } from "@sveltejs/kit";export const load: ServerLoad = async ({ locals, fetch, request }) => { const url = new URL(`${import.meta.env.VITE_API_BASE_URL}chronique/records/get_descriptions/`); if (params) { url.search = new URLSearchParams(params).toString(); } const response = await fetch(url, { method: 'GET' }); return { user: locals.user as User, }};
src/routes/login/+page.server.ts
- login form action
export const actions: Actions = { default: async ({ cookies, request, locals}) => { await logout(cookies); const data = await request.formData() as FormData; const username = data.get('username'); const password = data.get('password'); let response = await login(username, password) as Response; let json = await response.json() as TokenResponse; if (!response || response.status == 401) { return fail(400, { failure: true }); } let secure = import.meta.env.PROD ? true : false; const decoded = await jwt.verify(json.access, import.meta.env.VITE_SECRET_KEY.replace(/\\n/g, '\n'), { algorithms: ['RS256'], }) as jwt.VerifyOptions as JWTPayload; console.log('cookies set'); cookies.set('user_id', decoded.user_id, { path: '/', secure: secure, httpOnly: !secure, maxAge: 60 * 60 * 24 * 1000 }); cookies.set('access', json.access, { path: '/', secure: secure, httpOnly: !secure, maxAge: 60 * 60 * 24 * 1000 }); cookies.set('refresh', json.refresh, { path: '/', secure: secure, httpOnly: !secure, maxAge: 60 * 60 * 24 * 1000 });; // get user const api_response = await getUser({ access_token: json.access, user_id: decoded.user_id }) as Response | undefined; const response_json = await api_response.json() as UserApiResponse; let user = { id: decoded.user_id, username: response_json.username, email: response_json.email, } as User; locals.user = user; throw redirect(302, '/app'); },} satisfies Actions;
src/hooks.server.ts
import type { Handle, HandleFetch } from '@sveltejs/kit';export const handle: Handle = async ({ event, resolve }) => { const user_id = event.cookies.get('user_id') as string | undefined; const access_token = event.cookies.get('access') as string | undefined; const user = event.locals.user as User | undefined; console.log('user', user); if (access_token) console.log('has access token in handle'); if (user_id) console.log('has user id in handle'); if (!access_token) { if (event.url.pathname !== '/login') { await logout(event.cookies); } return resolve(event); } return resolve(event);};export const handleFetch: HandleFetch = async ({ event, request, fetch }) => { console.log('hooks - handleFetch') const access_token = event.cookies.get('access') as string | undefined; if (access_token) { console.log('has access token'); } else { console.log('no access token'); } if (access_token) { request.headers.set('Authorization', 'Bearer '+ access_token); } return await fetch(request);};
When I login, I can see from my console log in hooks that the access token makes it back to the hooks after logging in, however, when my src/routes/+page.svelte
loads, and calls the ServerLoad
, I can see from my log statements there are no cookies or access tokens available in getFetch.
My goal is to use fetch within a script tag, and not have to apply the cookies where the fetch is made from the script tag, but have them set in the request headers somewhere else