🐛 fix(auth): enable automatic token refresh across all web apps

Users were getting signed out after ~15 minutes because API clients were
reading tokens directly from localStorage without triggering the refresh
logic. The tokenManager exists with proper refresh capability but was
never being used.

Changes:
- Add getValidToken() method to auth stores in 9 web apps
- Update API clients to use authStore.getValidToken() instead of localStorage
- Token refresh now happens proactively before requests fail

Apps updated: chat, calendar, picture, zitare, contacts, todo, clock, manacore, manadeck

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Wuesteon 2025-12-10 20:52:29 +01:00
parent 6f74e1d9a6
commit 39b04e4b34
12 changed files with 209 additions and 33 deletions

View file

@ -3,10 +3,13 @@
*
* This replaces direct Supabase calls with backend API calls.
* All database operations now go through the NestJS backend.
*
* Token handling: Uses authStore.getValidToken() which automatically
* refreshes expired tokens before making requests.
*/
import { browser } from '$app/environment';
import { env } from '$env/dynamic/public';
import { authStore } from '$lib/stores/auth.svelte';
import type {
Conversation,
Message,
@ -46,12 +49,8 @@ async function fetchApi<T>(
): Promise<{ data: T | null; error: Error | null }> {
const { method = 'GET', body, token } = options;
// Get token from localStorage if not provided
// Token is stored by @manacore/shared-auth under '@auth/appToken'
let authToken = token;
if (!authToken && browser) {
authToken = localStorage.getItem('@auth/appToken') || undefined;
}
// Get a valid token (auto-refreshes if expired)
const authToken = token || (await authStore.getValidToken());
if (!authToken) {
return { data: null, error: new Error('No authentication token') };

View file

@ -34,6 +34,13 @@ function getAuthService() {
return _authService;
}
function getTokenManager() {
if (!browser) return null;
// Ensure auth service is initialized first
getAuthService();
return _tokenManager;
}
// State
let user = $state<UserData | null>(null);
let loading = $state(true);
@ -202,7 +209,8 @@ export const authStore = {
},
/**
* Get access token for API calls
* Get access token for API calls (raw token, no refresh)
* @deprecated Use getValidToken() instead for automatic refresh
*/
async getAccessToken() {
const authService = getAuthService();
@ -211,4 +219,16 @@ export const authStore = {
}
return await authService.getAppToken();
},
/**
* Get a valid access token for API calls
* Automatically refreshes if the token is expired or about to expire
*/
async getValidToken(): Promise<string | null> {
const tokenManager = getTokenManager();
if (!tokenManager) {
return null;
}
return await tokenManager.getValidToken();
},
};