refactor: update SSO handling and remove deprecated components
- Changed the hub-net network configuration to external in docker-compose. - Removed the Single Sign-On (SSO) service implementation and associated login form component. - Enhanced authentication callback logic to improve error handling and redirect management. - Updated various routes to streamline login and authentication processes, ensuring proper redirection to workspace login. - Cleaned up unused code and improved overall structure for better maintainability.
This commit is contained in:
157
frontend/src/lib/server/workspace-auth.ts
Normal file
157
frontend/src/lib/server/workspace-auth.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
import { env } from '$env/dynamic/private';
|
||||
import { redirect, type Cookies } from '@sveltejs/kit';
|
||||
|
||||
const DEFAULT_WORKSPACE_BASE_URL = 'https://workspace.aduanasoft.com';
|
||||
const RETURN_PATH_COOKIE = 'workspace_return_path';
|
||||
|
||||
function stripTrailingSlashes(value: string): string {
|
||||
return value.replace(/\/+$/, '');
|
||||
}
|
||||
|
||||
function isInternalOnlyHost(rawUrl: string): boolean {
|
||||
try {
|
||||
const parsed = new URL(rawUrl);
|
||||
const host = parsed.hostname.toLowerCase();
|
||||
return host === 'host.docker.internal' || host === 'backend' || host === 'hub-keycloak';
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getWorkspaceBaseUrl(): string {
|
||||
const candidates = [
|
||||
(env.VITE_HUB_URL || '').trim(),
|
||||
(env.HUB_URL || '').trim(),
|
||||
DEFAULT_WORKSPACE_BASE_URL
|
||||
].filter(Boolean);
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (!isInternalOnlyHost(candidate)) {
|
||||
return stripTrailingSlashes(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
return DEFAULT_WORKSPACE_BASE_URL;
|
||||
}
|
||||
|
||||
export type WorkspaceLoginUrlOptions = {
|
||||
/**
|
||||
* URL del login del Hub sin `return_to`. Usar en `post_logout_redirect_uri` para que,
|
||||
* tras logout en KC, el Hub aplique myApps() (launcher si el usuario tiene varias apps).
|
||||
* Con `return_to` a Anexo76, el re-login siempre rebotaba a esa app aunque hubiera más.
|
||||
*/
|
||||
forPostLogout?: boolean;
|
||||
};
|
||||
|
||||
export function getWorkspaceLoginUrl(
|
||||
systemBaseUrl: string,
|
||||
options?: WorkspaceLoginUrlOptions
|
||||
): string {
|
||||
const workspaceBaseUrl = getWorkspaceBaseUrl();
|
||||
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 `${workspaceBaseUrl}/login?return_to=${encodeURIComponent(loginUrl)}`;
|
||||
}
|
||||
|
||||
export function storeReturnPath(cookies: Cookies, path: string): void {
|
||||
if (!path || !path.startsWith('/')) return;
|
||||
cookies.set(RETURN_PATH_COOKIE, path, {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secure: env.NODE_ENV === 'production',
|
||||
maxAge: 60 * 10
|
||||
});
|
||||
}
|
||||
|
||||
export function getPublicKeycloakBaseUrl(): string {
|
||||
const configuredKeycloakUrl = (env.VITE_KEYCLOAK_URL || '').trim();
|
||||
if (configuredKeycloakUrl) {
|
||||
return stripTrailingSlashes(configuredKeycloakUrl);
|
||||
}
|
||||
|
||||
return `${getWorkspaceBaseUrl()}/kcauth`;
|
||||
}
|
||||
|
||||
export function getKeycloakRealm(): string {
|
||||
return (env.KEYCLOAK_REALM || env.VITE_KEYCLOAK_REALM || 'master').trim();
|
||||
}
|
||||
|
||||
export function getKeycloakClientId(): string {
|
||||
return (env.KEYCLOAK_CLIENT_ID || env.VITE_KEYCLOAK_CLIENT_ID || 'anexo76-frontend').trim();
|
||||
}
|
||||
|
||||
export function getCleanReturnPath(url: URL): string {
|
||||
const cleanParams = new URLSearchParams(url.searchParams);
|
||||
cleanParams.delete('sso_verified');
|
||||
|
||||
const queryString = cleanParams.toString();
|
||||
return queryString ? `${url.pathname}?${queryString}` : url.pathname;
|
||||
}
|
||||
|
||||
export function storeWorkspaceReturnPath(cookies: Cookies, url: URL): string {
|
||||
const returnPath = getCleanReturnPath(url);
|
||||
|
||||
cookies.set(RETURN_PATH_COOKIE, returnPath, {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secure: env.NODE_ENV === 'production',
|
||||
maxAge: 60 * 10
|
||||
});
|
||||
|
||||
return returnPath;
|
||||
}
|
||||
|
||||
export function readWorkspaceReturnPath(cookies: Cookies, fallbackPath: string): string {
|
||||
const storedReturnPath = cookies.get(RETURN_PATH_COOKIE);
|
||||
if (storedReturnPath && storedReturnPath.startsWith('/')) {
|
||||
return storedReturnPath;
|
||||
}
|
||||
|
||||
return fallbackPath;
|
||||
}
|
||||
|
||||
export function clearWorkspaceReturnPath(cookies: Cookies): void {
|
||||
cookies.delete(RETURN_PATH_COOKIE, { path: '/' });
|
||||
}
|
||||
|
||||
export function buildKeycloakAuthorizationUrl(systemBaseUrl: string, redirectPath: string): string {
|
||||
const keycloakBaseUrl = getPublicKeycloakBaseUrl();
|
||||
const redirectUri = `${systemBaseUrl}/auth/callback`;
|
||||
const state = JSON.stringify({ redirect_url: redirectPath });
|
||||
const params = new URLSearchParams({
|
||||
client_id: getKeycloakClientId(),
|
||||
redirect_uri: redirectUri,
|
||||
response_type: 'code',
|
||||
scope: 'openid',
|
||||
prompt: 'none',
|
||||
state
|
||||
});
|
||||
|
||||
return `${keycloakBaseUrl}/realms/${getKeycloakRealm()}/protocol/openid-connect/auth?${params.toString()}`;
|
||||
}
|
||||
|
||||
export function redirectToWorkspaceLogin(cookies: Cookies, url: URL): never {
|
||||
storeWorkspaceReturnPath(cookies, url);
|
||||
throw redirect(303, getWorkspaceLoginUrl(url.origin));
|
||||
}
|
||||
|
||||
export function redirectToKeycloakAuthorization(systemBaseUrl: string, redirectPath: string): never {
|
||||
throw redirect(303, buildKeycloakAuthorizationUrl(systemBaseUrl, redirectPath));
|
||||
}
|
||||
|
||||
export function buildKeycloakLogoutUrl(systemBaseUrl: string): string {
|
||||
const keycloakBaseUrl = getPublicKeycloakBaseUrl();
|
||||
const workspaceLoginUrl = getWorkspaceLoginUrl(systemBaseUrl, { forPostLogout: true });
|
||||
const params = new URLSearchParams({
|
||||
client_id: getKeycloakClientId(),
|
||||
post_logout_redirect_uri: workspaceLoginUrl
|
||||
});
|
||||
|
||||
return `${keycloakBaseUrl}/realms/${getKeycloakRealm()}/protocol/openid-connect/logout?${params.toString()}`;
|
||||
}
|
||||
Reference in New Issue
Block a user