mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-22 15:26:41 +02:00
🐛 fix(shared-auth): add automatic token refresh on 401 responses
- Add backendUrl parameter to initializeWebAuth() for interceptor config - Expand isTokenExpiredResponse() to match more error patterns: - "invalid token", "token validation failed", "claim" (jose errors) - ERR_JWT_EXPIRED error code - Update all web apps to pass backendUrl for automatic refresh: - picture (3006), chat (3002), zitare (3007), contacts (3015) - calendar (3014), clock (3017), todo (3018) - Fix API client default port in picture web app This prevents users from being randomly signed out when JWT expires. The interceptor now catches 401 responses and automatically refreshes the token before retrying the request.
This commit is contained in:
parent
b44e515507
commit
0fa154c7d6
10 changed files with 106 additions and 18 deletions
|
|
@ -20,6 +20,16 @@ function getAuthUrl(): string {
|
|||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3014';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3014';
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null = null;
|
||||
|
|
@ -27,7 +37,10 @@ let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null =
|
|||
function getAuthService() {
|
||||
if (!browser) return null;
|
||||
if (!_authService) {
|
||||
const auth = initializeWebAuth({ baseUrl: getAuthUrl() });
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: getAuthUrl(),
|
||||
backendUrl: getBackendUrl(), // Enables automatic token refresh on 401 responses
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,16 @@ function getAuthUrl(): string {
|
|||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3002';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3002';
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null = null;
|
||||
|
|
@ -27,7 +37,10 @@ let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null =
|
|||
function getAuthService() {
|
||||
if (!browser) return null;
|
||||
if (!_authService) {
|
||||
const auth = initializeWebAuth({ baseUrl: getAuthUrl() });
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: getAuthUrl(),
|
||||
backendUrl: getBackendUrl(), // Enables automatic token refresh on 401 responses
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,16 @@ function getAuthUrl(): string {
|
|||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3017';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3017';
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null = null;
|
||||
|
|
@ -26,7 +36,10 @@ let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null =
|
|||
function getAuthService() {
|
||||
if (!browser) return null;
|
||||
if (!_authService) {
|
||||
const auth = initializeWebAuth({ baseUrl: getAuthUrl() });
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: getAuthUrl(),
|
||||
backendUrl: getBackendUrl(), // Enables automatic token refresh on 401 responses
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import { initializeWebAuth } from '@manacore/shared-auth';
|
|||
import type { UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Initialize Mana Core Auth only on the client side
|
||||
// TODO: Use PUBLIC_MANA_CORE_AUTH_URL from env when available
|
||||
const MANA_AUTH_URL = 'http://localhost:3001';
|
||||
const BACKEND_URL = 'http://localhost:3015';
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
|
|
@ -18,7 +18,10 @@ let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null =
|
|||
function getAuthService() {
|
||||
if (!browser) return null;
|
||||
if (!_authService) {
|
||||
const auth = initializeWebAuth({ baseUrl: MANA_AUTH_URL });
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: MANA_AUTH_URL,
|
||||
backendUrl: BACKEND_URL, // Enables automatic token refresh on 401 responses
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,16 @@
|
|||
* API Client for Picture Backend
|
||||
* Replaces direct Supabase calls with backend API calls.
|
||||
*
|
||||
* Token handling: Uses authStore.getValidToken() which automatically
|
||||
* refreshes expired tokens before making requests.
|
||||
* Token handling:
|
||||
* - Uses authStore.getValidToken() which automatically refreshes expired tokens
|
||||
* - The fetch interceptor (setupFetchInterceptor) handles 401 responses by refreshing and retrying
|
||||
* - If refresh fails, the request fails and user should be redirected to login
|
||||
*/
|
||||
|
||||
import { env } from '$env/dynamic/public';
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
|
||||
const API_BASE = env.PUBLIC_BACKEND_URL || 'http://localhost:3003';
|
||||
const API_BASE = env.PUBLIC_BACKEND_URL || 'http://localhost:3006';
|
||||
|
||||
type FetchOptions = {
|
||||
method?: 'GET' | 'POST' | 'PATCH' | 'DELETE';
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { browser } from '$app/environment';
|
|||
import { env } from '$env/dynamic/public';
|
||||
|
||||
const MANA_AUTH_URL = env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
const BACKEND_URL = env.PUBLIC_BACKEND_URL || 'http://localhost:3006';
|
||||
|
||||
export interface UserData {
|
||||
id: string;
|
||||
|
|
@ -28,7 +29,10 @@ async function getAuthService() {
|
|||
if (!_authService) {
|
||||
try {
|
||||
const { initializeWebAuth } = await import('@manacore/shared-auth');
|
||||
const auth = initializeWebAuth({ baseUrl: MANA_AUTH_URL });
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: MANA_AUTH_URL,
|
||||
backendUrl: BACKEND_URL, // Enables automatic token refresh on 401 responses
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,16 @@ function getAuthUrl(): string {
|
|||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3018';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3018';
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null = null;
|
||||
|
|
@ -27,7 +37,10 @@ let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null =
|
|||
function getAuthService() {
|
||||
if (!browser) return null;
|
||||
if (!_authService) {
|
||||
const auth = initializeWebAuth({ baseUrl: getAuthUrl() });
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: getAuthUrl(),
|
||||
backendUrl: getBackendUrl(), // Enables automatic token refresh on 401 responses
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import { initializeWebAuth } from '@manacore/shared-auth';
|
|||
import type { UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Initialize Mana Core Auth only on the client side
|
||||
// TODO: Use PUBLIC_MANA_CORE_AUTH_URL from env when available
|
||||
const MANA_AUTH_URL = 'http://localhost:3001';
|
||||
const BACKEND_URL = 'http://localhost:3007';
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
|
|
@ -18,7 +18,10 @@ let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null =
|
|||
function getAuthService() {
|
||||
if (!browser) return null;
|
||||
if (!_authService) {
|
||||
const auth = initializeWebAuth({ baseUrl: MANA_AUTH_URL });
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: MANA_AUTH_URL,
|
||||
backendUrl: BACKEND_URL, // Enables automatic token refresh on 401 responses
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue