Issue Description:
- I'm building a web application using Svelte and Node.js.
- The application has user authentication using JWT tokens, and you store these tokens and user information in cookies.
- The authentication status is not persisting between page refreshes. Even though you're seeing the tokens and user data in your console, the UI doesn't reflect the correct login/logout state.
Although I'm getting authToken, refreshToken cookies and userId each time I refresh my webpage, it's not being persistent
- Not logged In - I supposed to see Login/Registration
- Logged in - I supposed to see Logoug/Profile
When trying to logging in, I get to see Logout button, but on refresh it's gone (showing login/register again) although my console.log is showing that cookies and user data on page refresh are present
I tried to write stores to differentiate, but it's not helping. I'm connected to NodeJS server by the way. My Postman(backend) works like a charm, but frontend doesn't work well.
stores.ts
import { writable } from 'svelte/store';
export const UserId = writable(null);
export const setUserId = (id) => {
UserId.set(id);
return UserId;
};
// ---------------------------------------------
export const Authenticated = writable(false);
// Function to update the Authenticated store
export const setUserAuthenticated = (auth) => {
Authenticated.set(auth);
return Authenticated;
};
Navbar.svelte
{#if $Authenticated}
<div class="button-container">
<Button
element="a"
href="/profile"
variant="outline"
color="green">Profile
</Button>
</div>
<div class="button-container" on:click={handleSubmit}>
<Button
element="a"
href="/"
variant="outline"
color="red">Logout
</Button>
</div>
{:else }
<div class="button-container">
<Button
element="a"
href="/login"
variant="outline"
color="green">Login
</Button>
</div>
<div class="button-container">
<Button
element="a"
href="/register"
variant="outline"
color="red">Registration
</Button>
</div>
{/if}
+layout.server.ts
import type { LayoutServerLoad } from './$types';
import jwt from "jsonwebtoken";
import {setUserAuthenticated, UserId} from "$helpers/stores";
export const load: LayoutServerLoad = async ({ cookies }) => {
const authToken = cookies.get('auth-token');
const refreshToken = cookies.get('refresh-token');
console.log('Auth token in LAYOUT.SERVER::::::::: ', authToken);
console.log('Refresh token in LAYOUT.SERVER::::::::: ', refreshToken);
function handleAuthentication(authToken) {
let userId = null;
UserId.subscribe((uid) => {
userId = uid;
});
if (!authToken) {
console.log('No authToken present');
setUserAuthenticated(false);
return {
user: null,
};
}
try {
const secretKey = 'farmTokenSecrets';
const decodedAuthToken = jwt.verify(authToken, secretKey);
userId = decodedAuthToken.userId ?? userId;
setUserAuthenticated(true); // Update the Authenticated store
console.log('User ID in LAYOUT.SERVER::::::::: ', userId);
return {
user: {
userId: userId,
},
};
} catch (error) {
console.error('Error decoding auth-token:', error);
setUserAuthenticated(false);
return {
user: null,
};
}
}
return handleAuthentication(authToken);
};
After digging around in the docs a bit, I believe this chapter in the docs should be exactly what you need. I mentioned in the comments that you shouldn't use stores in the load but I didn't mention what's the alternative (because I didn't know it for sure myself), but using the svelte context in combination with stores should be what you are looking for.