Merge pull request 'fix/logout-anexo' (#392) from fix/logout-anexo into development

Reviewed-on: ADUANASOFT/anexo76#392
This commit is contained in:
2026-05-12 22:46:49 +00:00
9 changed files with 51 additions and 15 deletions

View File

@@ -9,6 +9,7 @@ import {
getAccessTokenFromCookies,
setAccessTokenCookies
} from '$lib/server/access-token-cookie';
import { isSecureContext } from '$lib/server/workspace-auth';
/**
* Obtiene y normaliza la URL base de la API para llamadas desde el servidor
@@ -57,7 +58,7 @@ export function setAuthTokens(
refreshToken?: string
) {
setAccessTokenCookies(cookies, accessToken, {
secure: process.env.NODE_ENV === 'production',
secure: isSecureContext(),
maxAge: 60 * 60 * 24 * 7 // 7 días
});
@@ -66,7 +67,7 @@ export function setAuthTokens(
path: '/',
httpOnly: true, // *** HttpOnly: JS nunca lee el refresh_token ***
sameSite: 'lax',
secure: process.env.NODE_ENV === 'production',
secure: isSecureContext(),
maxAge: 60 * 60 * 24 * 30 // 30 días
});
}

View File

@@ -4,6 +4,17 @@ import { redirect, type Cookies } from '@sveltejs/kit';
const DEFAULT_WORKSPACE_BASE_URL = 'https://workspace.aduanasoft.com';
const RETURN_PATH_COOKIE = 'workspace_return_path';
/**
* Returns true only when the public-facing URL uses HTTPS.
* Use this for cookie `secure` flag instead of NODE_ENV so that
* cookies work on HTTP LAN dev environments (e.g. 192.168.x.x).
*/
export function isSecureContext(): boolean {
const origin = (env.ORIGIN || process.env.ORIGIN || '').trim();
if (origin) return origin.startsWith('https://');
return process.env.NODE_ENV === 'production';
}
function stripTrailingSlashes(value: string): string {
return value.replace(/\/+$/, '');
}
@@ -51,9 +62,9 @@ export function getWorkspaceLoginUrl(
if (options?.forPostLogout) {
return `${workspaceBaseUrl}/login`;
}
// return_to points to /login so that after Workspace auth the browser lands on
// /login, which immediately attempts a prompt=none KC auth.
const loginUrl = `${systemBaseUrl}/login`;
// return_to includes sso_verified=1 so the workspace preserves it when redirecting
// back, regardless of what additional params the workspace appends.
const loginUrl = `${systemBaseUrl}/login?sso_verified=1`;
return `${workspaceBaseUrl}/login?return_to=${encodeURIComponent(loginUrl)}`;
}
@@ -63,7 +74,7 @@ export function storeReturnPath(cookies: Cookies, path: string): void {
path: '/',
httpOnly: true,
sameSite: 'lax',
secure: env.NODE_ENV === 'production',
secure: isSecureContext(),
maxAge: 60 * 10
});
}
@@ -100,7 +111,7 @@ export function storeWorkspaceReturnPath(cookies: Cookies, url: URL): string {
path: '/',
httpOnly: true,
sameSite: 'lax',
secure: env.NODE_ENV === 'production',
secure: isSecureContext(),
maxAge: 60 * 10
});
@@ -147,10 +158,14 @@ export function redirectToKeycloakAuthorization(systemBaseUrl: string, redirectP
export function buildKeycloakLogoutUrl(systemBaseUrl: string): string {
const keycloakBaseUrl = getPublicKeycloakBaseUrl();
const workspaceLoginUrl = getWorkspaceLoginUrl(systemBaseUrl, { forPostLogout: true });
// post_logout_redirect_uri must be a URI registered in the KC client.
// The workspace login URL (workspace.aduanasoft.com/login) is NOT registered there.
// Use a local /auth/post-logout route which IS covered by the app's registered wildcard,
// then that route bounces to workspace login.
const postLogoutRedirectUri = `${systemBaseUrl}/auth/post-logout`;
const params = new URLSearchParams({
client_id: getKeycloakClientId(),
post_logout_redirect_uri: workspaceLoginUrl
post_logout_redirect_uri: postLogoutRedirectUri
});
return `${keycloakBaseUrl}/realms/${getKeycloakRealm()}/protocol/openid-connect/logout?${params.toString()}`;