Merge pull request 'refactor: centralize access token handling in cookies and improve related functions' (#356) from feature/cookies into development

Reviewed-on: ADUANASOFT/anexo76#356
This commit is contained in:
2026-05-02 02:38:48 +00:00
31 changed files with 256 additions and 91 deletions

View File

@@ -15,6 +15,7 @@
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');
@@ -36,7 +37,7 @@ export const POST = async ({ cookies, fetch }: RequestEvent) => {
// 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: '/' });
cookies.delete('access_token', { path: '/' });
clearAccessTokenCookies(cookies);
cookies.delete('active_company_id', { path: '/' });
const status = response.status === 401 ? 401 : 400;

View File

@@ -1,7 +1,8 @@
import type { RequestHandler } from './$types';
import { getAccessTokenFromCookies } from '$lib/server/access-token-cookie';
export const GET: RequestHandler = async ({ cookies, url }) => {
const token = cookies.get('access_token');
const token = getAccessTokenFromCookies(cookies);
// Obtener company_id de la cookie
const companyId = cookies.get('active_company_id');

View File

@@ -1,7 +1,8 @@
import type { RequestHandler } from './$types';
import { getAccessTokenFromCookies } from '$lib/server/access-token-cookie';
export const GET: RequestHandler = async ({ cookies, url, params }) => {
const token = cookies.get('access_token');
const token = getAccessTokenFromCookies(cookies);
const { id } = params;
// Obtener company_id de la cookie o query params

View File

@@ -3,9 +3,10 @@
*/
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { getAccessTokenFromCookies } from '$lib/server/access-token-cookie';
export const GET: RequestHandler = async ({ cookies, fetch }) => {
const token = cookies.get('access_token');
const token = getAccessTokenFromCookies(cookies);
if (!token) {
// Limpiar cualquier cookie de compañía si no hay autenticación

View File

@@ -1,7 +1,8 @@
import type { RequestHandler } from './$types';
import { getAccessTokenFromCookies } from '$lib/server/access-token-cookie';
export const GET: RequestHandler = async ({ cookies, url }) => {
const token = cookies.get('access_token');
const token = getAccessTokenFromCookies(cookies);
// Configurar la URL de la API usando las variables de entorno
let apiUrl = process.env.INTERNAL_API_URL;

View File

@@ -1,7 +1,8 @@
import type { RequestHandler } from './$types';
import { getAccessTokenFromCookies } from '$lib/server/access-token-cookie';
export const GET: RequestHandler = async ({ cookies, url }) => {
const token = cookies.get('access_token');
const token = getAccessTokenFromCookies(cookies);
// Obtener company_id de la cookie
const companyId = cookies.get('active_company_id');

View File

@@ -1,7 +1,8 @@
import type { RequestHandler } from './$types';
import { getAccessTokenFromCookies } from '$lib/server/access-token-cookie';
export const GET: RequestHandler = async ({ cookies, url }) => {
const token = cookies.get('access_token');
const token = getAccessTokenFromCookies(cookies);
// Obtener company_id de la cookie
const companyId = cookies.get('active_company_id');

View File

@@ -1,7 +1,8 @@
import type { RequestHandler } from './$types';
import { getAccessTokenFromCookies } from '$lib/server/access-token-cookie';
export const GET: RequestHandler = async ({ cookies, url, params }) => {
const token = cookies.get('access_token');
const token = getAccessTokenFromCookies(cookies);
const { id } = params;
// Obtener company_id de la cookie o query params

View File

@@ -1,7 +1,8 @@
import type { RequestHandler } from './$types';
import { getAccessTokenFromCookies } from '$lib/server/access-token-cookie';
export const GET: RequestHandler = async ({ cookies, url }) => {
const token = cookies.get('access_token');
const token = getAccessTokenFromCookies(cookies);
// Configurar la URL de la API usando las variables de entorno
let apiUrl = process.env.INTERNAL_API_URL;

View File

@@ -1,7 +1,8 @@
import type { RequestHandler } from './$types';
import { getAccessTokenFromCookies } from '$lib/server/access-token-cookie';
export const GET: RequestHandler = async ({ cookies, url }) => {
const token = cookies.get('access_token');
const token = getAccessTokenFromCookies(cookies);
// Configurar la URL de la API usando las variables de entorno
let apiUrl = process.env.INTERNAL_API_URL;

View File

@@ -1,7 +1,8 @@
import type { RequestHandler } from './$types';
import { getAccessTokenFromCookies } from '$lib/server/access-token-cookie';
export const GET: RequestHandler = async ({ cookies, url }) => {
const token = cookies.get('access_token');
const token = getAccessTokenFromCookies(cookies);
// Obtener company_id de la cookie
const companyId = cookies.get('active_company_id');

View File

@@ -1,7 +1,8 @@
import type { RequestHandler } from './$types';
import { getAccessTokenFromCookies } from '$lib/server/access-token-cookie';
export const GET: RequestHandler = async ({ cookies, params, url }) => {
const token = cookies.get('access_token');
const token = getAccessTokenFromCookies(cookies);
const { id } = params;
// Obtener company_id de la cookie o query params

View File

@@ -1,5 +1,6 @@
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
import { setAccessTokenCookies } from '$lib/server/access-token-cookie';
export const load: PageServerLoad = async ({ url, cookies, fetch }) => {
// Obtener el código y state de los query params
@@ -61,11 +62,8 @@ export const load: PageServerLoad = async ({ url, cookies, fetch }) => {
// refresh_token → HttpOnly (el JS nunca lo lee; el servidor lo gestiona)
const isProduction = process.env.NODE_ENV === 'production';
cookies.set('access_token', tokens.access_token, {
path: '/',
httpOnly: false, // El cliente necesita leerlo para Bearer
setAccessTokenCookies(cookies, tokens.access_token, {
secure: isProduction,
sameSite: 'lax',
maxAge: 60 * 60 * 24 * 7 // 7 días
});

View File

@@ -6,6 +6,7 @@
*/
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
import { setAccessTokenCookies } from '$lib/server/access-token-cookie';
export const load: PageServerLoad = async ({ url, cookies }) => {
const relayToken = url.searchParams.get('relay');
@@ -54,12 +55,9 @@ export const load: PageServerLoad = async ({ url, cookies }) => {
const isProduction = process.env.NODE_ENV === 'production';
console.log('[SSO] NODE_ENV:', process.env.NODE_ENV, '→ isProduction:', isProduction);
// access_token — NO HttpOnly (client JS reads it for Bearer headers)
cookies.set('access_token', tokens.access_token, {
path: '/',
httpOnly: false,
// access_token — NO HttpOnly (Bearer desde JS); fragmentado si el JWT supera ~4KB
setAccessTokenCookies(cookies, tokens.access_token, {
secure: isProduction,
sameSite: 'lax',
maxAge: 60 * 60 * 24 * 7,
});

View File

@@ -1,6 +1,7 @@
<script lang="ts">
import { onMount } from 'svelte';
import { browser } from '$app/environment';
import { getAccessTokenFromDocument } from '$lib/access-token-cookie-browser';
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import {
@@ -56,7 +57,7 @@
if (parts.length === 2) return parts.pop()?.split(';').shift() || null;
return null;
};
const cookieToken = getCookie('access_token');
const cookieToken = getAccessTokenFromDocument();
const localToken = localStorage.getItem('access_token');
if (cookieToken && cookieToken !== localToken)
localStorage.setItem('access_token', cookieToken);

View File

@@ -22,6 +22,7 @@
import { Label } from '$lib/components/ui/label';
import type { PageData } from './$types';
import { browser } from '$app/environment';
import { getAccessTokenFromDocument } from '$lib/access-token-cookie-browser';
import { currentUser } from '$lib/auth';
import { companyStore } from '$lib/stores/company.svelte';
import { getCompany } from '$lib/api/dashboard/a76/general_catalogs/company';
@@ -193,7 +194,7 @@
};
// Verificar si hay token en las cookies
const cookieToken = getCookie('access_token');
const cookieToken = getAccessTokenFromDocument();
const localToken = localStorage.getItem('access_token');
if (cookieToken && cookieToken !== localToken) {

View File

@@ -10,8 +10,9 @@
import * as Dialog from '$lib/components/ui/dialog';
import type { PageData } from './$types';
import { browser } from '$app/environment';
import { getAccessTokenFromDocument } from '$lib/access-token-cookie-browser';
import { companyStore } from '$lib/stores/company.svelte';
import { Edit, Send, Plus, Trash2, RefreshCw } from 'lucide-svelte';
import { Edit, Send, Plus, Trash2, RefreshCw } from 'lucide-svelte';
import { obtenerAtajosListaPedimento } from '$lib/config/shortcuts/dashboard/pedimentos/list';
import { useShortcuts } from '$lib/hooks/use-shortcuts';
import { goto } from '$app/navigation';
@@ -45,7 +46,7 @@ let filters = $state({
};
// Verificar si hay token en las cookies
const cookieToken = getCookie('access_token');
const cookieToken = getAccessTokenFromDocument();
const localToken = localStorage.getItem('access_token');
if (cookieToken && cookieToken !== localToken) {

View File

@@ -13,6 +13,7 @@
import { obtenerAtajosLista } from '$lib/config/shortcuts/dashboard/reference_data/countries/list';
import { browser } from '$app/environment';
import { currentUser, userHasPermission } from '$lib/auth';
import { getAccessTokenFromDocument } from '$lib/access-token-cookie-browser';
import ErrorState from '$lib/components/dashboard/common/error-state.svelte';
// Los datos iniciales vienen del servidor
@@ -36,7 +37,7 @@
return null;
};
const cookieToken = getCookie('access_token');
const cookieToken = getAccessTokenFromDocument();
const localToken = localStorage.getItem('access_token');
if (cookieToken && cookieToken !== localToken) {

View File

@@ -13,6 +13,7 @@
import { obtenerAtajosLista } from '$lib/config/shortcuts/dashboard/reference_data/currency_types/list';
import { browser } from '$app/environment';
import { currentUser, userHasPermission } from '$lib/auth';
import { getAccessTokenFromDocument } from '$lib/access-token-cookie-browser';
import ErrorState from '$lib/components/dashboard/common/error-state.svelte';
// Los datos iniciales vienen del servidor
@@ -36,7 +37,7 @@
return null;
};
const cookieToken = getCookie('access_token');
const cookieToken = getAccessTokenFromDocument();
const localToken = localStorage.getItem('access_token');
if (cookieToken && cookieToken !== localToken) {
localStorage.setItem('access_token', cookieToken);

View File

@@ -1,6 +1,7 @@
<script lang="ts">
import { onMount } from 'svelte';
import { browser } from '$app/environment';
import { getAccessTokenFromDocument } from '$lib/access-token-cookie-browser';
import { page } from '$app/stores';
import * as Card from '$lib/components/ui/card';
import { Button } from '$lib/components/ui/button';
@@ -26,7 +27,7 @@
if (parts.length === 2) return parts.pop()?.split(';').shift() || null;
return null;
};
const cookieToken = getCookie('access_token');
const cookieToken = getAccessTokenFromDocument();
const localToken = localStorage.getItem('access_token');
if (cookieToken && cookieToken !== localToken) localStorage.setItem('access_token', cookieToken);
}

View File

@@ -1,6 +1,7 @@
import { redirect } from '@sveltejs/kit';
import { env } from '$env/dynamic/private';
import type { RequestHandler } from './$types';
import { clearAccessTokenCookies } from '$lib/server/access-token-cookie';
export const POST: RequestHandler = async ({ cookies, request }) => {
const refreshToken = cookies.get('refresh_token');
@@ -14,8 +15,8 @@ export const POST: RequestHandler = async ({ cookies, request }) => {
? `${hubPublicUrl}/login`
: `${new URL(request.url).origin}/login`;
// Eliminar todas las cookies de autenticación
cookies.delete('access_token', { path: '/' });
// Eliminar todas las cookies de autenticación (access_token puede estar fragmentado)
clearAccessTokenCookies(cookies);
cookies.delete('refresh_token', { path: '/' });
cookies.delete('active_company_id', { path: '/' });
cookies.delete('sso_tenant_id', { path: '/' });