mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-20 10:53:40 +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
|
|
@ -81,13 +81,21 @@ export type { ContactsClientConfig, ContactSearchOptions } from './clients/conta
|
|||
* ```typescript
|
||||
* import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
*
|
||||
* // Basic setup (interceptor only for auth URL)
|
||||
* const { authService, tokenManager } = initializeWebAuth({
|
||||
* baseUrl: 'https://api.example.com',
|
||||
* baseUrl: 'https://auth.example.com',
|
||||
* });
|
||||
*
|
||||
* // With backend URL (interceptor for both auth and backend - recommended)
|
||||
* const { authService, tokenManager } = initializeWebAuth({
|
||||
* baseUrl: 'https://auth.example.com',
|
||||
* backendUrl: 'https://api.example.com',
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function initializeWebAuth(config: {
|
||||
baseUrl: string;
|
||||
backendUrl?: string;
|
||||
storageKeys?: Partial<import('./types').StorageKeys>;
|
||||
}) {
|
||||
// Set up adapters
|
||||
|
|
@ -99,8 +107,15 @@ export function initializeWebAuth(config: {
|
|||
const authService = _createAuthService(config);
|
||||
const tokenManager = _createTokenManager(authService);
|
||||
|
||||
// Set up interceptor
|
||||
// Set up interceptor for auth URL
|
||||
_setupFetchInterceptor(authService, tokenManager);
|
||||
|
||||
// Set up interceptor for backend URL if provided (for automatic token refresh on 401)
|
||||
if (config.backendUrl) {
|
||||
_setupFetchInterceptor(authService, tokenManager, {
|
||||
backendUrl: config.backendUrl,
|
||||
});
|
||||
}
|
||||
|
||||
return { authService, tokenManager };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,8 +201,9 @@ async function makeRequestWithToken(
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if response indicates token expiration
|
||||
* Only return true for explicit token expiration, not generic unauthorized errors
|
||||
* Check if response indicates a token issue that warrants a refresh attempt
|
||||
* Any 401 response should trigger a refresh attempt - if the refresh fails,
|
||||
* then we know the session is truly invalid
|
||||
*/
|
||||
function isTokenExpiredResponse(responseData: Record<string, unknown>): boolean {
|
||||
const error = responseData.error as Record<string, unknown> | undefined;
|
||||
|
|
@ -211,13 +212,21 @@ function isTokenExpiredResponse(responseData: Record<string, unknown>): boolean
|
|||
).toLowerCase();
|
||||
const errorCode = String(responseData.code || error?.code || '');
|
||||
|
||||
// Only trigger refresh for explicit token expiration messages
|
||||
// Trigger refresh for any token-related auth error
|
||||
// This includes:
|
||||
// - Explicit expiration: "jwt expired", "token expired"
|
||||
// - Generic validation failures: "invalid token", "token validation failed"
|
||||
// - Backend passthrough errors: "exp claim", "claim timestamp"
|
||||
return (
|
||||
errorMessage.includes('jwt expired') ||
|
||||
errorMessage.includes('token expired') ||
|
||||
errorMessage.includes('token has expired') ||
|
||||
errorMessage.includes('invalid token') ||
|
||||
errorMessage.includes('token validation failed') ||
|
||||
errorMessage.includes('claim') || // Catches jose errors like "exp claim timestamp check failed"
|
||||
errorCode === 'PGRST301' ||
|
||||
errorCode === 'TOKEN_EXPIRED'
|
||||
errorCode === 'TOKEN_EXPIRED' ||
|
||||
errorCode === 'ERR_JWT_EXPIRED'
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue