- Introduced utility functions for managing access tokens in cookies, including setting, getting, and clearing tokens. - Updated various components and server routes to utilize the new access token functions for better consistency and maintainability. - Removed redundant cookie handling code across the application, streamlining the authentication process.
63 lines
2.3 KiB
TypeScript
63 lines
2.3 KiB
TypeScript
/**
|
|
* Endpoint server-side para el refresh silencioso del access token.
|
|
*
|
|
* Flujo de seguridad:
|
|
* 1. El cliente llama a POST /api-sveltekit/auth/silent-refresh con credentials:'include'
|
|
* (las cookies HttpOnly se envían automáticamente, sin que JS las lea).
|
|
* 2. Este servidor lee el refresh_token de la cookie HttpOnly.
|
|
* 3. Llama al backend FastAPI /v1/auth/refresh con el refresh_token.
|
|
* 4. Si es exitoso, actualiza las cookies HttpOnly con los nuevos tokens.
|
|
* 5. Retorna solo el access_token al cliente (el refresh_token permanece en HttpOnly).
|
|
*
|
|
* De este modo el refresh_token NUNCA toca el código JavaScript del cliente.
|
|
*/
|
|
|
|
import { json } from '@sveltejs/kit';
|
|
import type { RequestEvent } from '@sveltejs/kit';
|
|
import { getServerApiUrl, setAuthTokens } from '$lib/server/api';
|
|
import { clearAccessTokenCookies } from '$lib/server/access-token-cookie';
|
|
|
|
export const POST = async ({ cookies, fetch }: RequestEvent) => {
|
|
const refreshToken = cookies.get('refresh_token');
|
|
|
|
if (!refreshToken) {
|
|
return json({ error: 'No refresh token available' }, { status: 401 });
|
|
}
|
|
|
|
try {
|
|
const baseUrl = getServerApiUrl();
|
|
|
|
const response = await fetch(`${baseUrl}v1/auth/refresh`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ refresh_token: refreshToken })
|
|
});
|
|
|
|
if (!response.ok) {
|
|
// El refresh token expiró o fue invalidado por Keycloak (sesión terminada).
|
|
// Limpiar las cookies para que el servidor redirigir al login en la siguiente carga.
|
|
cookies.delete('refresh_token', { path: '/' });
|
|
clearAccessTokenCookies(cookies);
|
|
cookies.delete('active_company_id', { path: '/' });
|
|
|
|
const status = response.status === 401 ? 401 : 400;
|
|
return json({ error: 'Refresh token expired or invalid' }, { status });
|
|
}
|
|
|
|
const data = (await response.json()) as {
|
|
access_token: string;
|
|
refresh_token?: string;
|
|
expires_in?: number;
|
|
};
|
|
|
|
// Actualizar las cookies HttpOnly con los nuevos tokens
|
|
setAuthTokens(cookies, data.access_token, data.refresh_token);
|
|
|
|
// Devolver solo el access_token al cliente
|
|
return json({ access_token: data.access_token });
|
|
} catch (error) {
|
|
console.error('[silent-refresh] Error inesperado:', error);
|
|
return json({ error: 'Internal server error' }, { status: 500 });
|
|
}
|
|
};
|