export interface AdminAuthRedirectUris { redirectUri: string; postLogoutRedirectUri: string; popupRedirectUri: string; } export const ADMIN_AUTH_CALLBACK_PATH = "/auth/callback"; const ADMIN_DEFAULT_PRODUCTION_OIDC_AUTHORITY = "https://sso.hmac.kr/oidc"; const ADMIN_LOCAL_OIDC_PORT = "5000"; export function resolveAdminPublicOrigin( configuredOrigin: string | undefined, browserOrigin: string, ) { const trimmed = configuredOrigin?.trim(); if (!trimmed) { return browserOrigin; } try { return new URL(trimmed).origin; } catch { return browserOrigin; } } export function buildAdminAuthRedirectUris( publicOrigin: string, ): AdminAuthRedirectUris { return { redirectUri: `${publicOrigin}${ADMIN_AUTH_CALLBACK_PATH}`, postLogoutRedirectUri: publicOrigin, popupRedirectUri: `${publicOrigin}${ADMIN_AUTH_CALLBACK_PATH}`, }; } export type BrowserPkceLoginCheck = { isSecureContext?: boolean; origin?: string; cryptoSubtleAvailable?: boolean; }; const devTrustedPkceHosts = new Set([ "localhost", "127.0.0.1", "::1", "host.docker.internal", ]); function isPrivateIPv4(hostname: string) { const parts = hostname.split(".").map((part) => Number.parseInt(part, 10)); if ( parts.length !== 4 || parts.some((part) => Number.isNaN(part) || part < 0 || part > 255) ) { return false; } const [first, second] = parts; return ( first === 10 || (first === 172 && second >= 16 && second <= 31) || (first === 192 && second === 168) ); } function isDevTrustedPkceOrigin(origin: string) { try { const hostname = new URL(origin).hostname; return devTrustedPkceHosts.has(hostname) || isPrivateIPv4(hostname); } catch { return false; } } export function resolveAdminOidcAuthority( configuredAuthority: string | undefined, browserOrigin: string, ) { const trimmed = configuredAuthority?.trim(); if (trimmed) { return trimmed; } try { const originUrl = new URL(browserOrigin); if (isDevTrustedPkceOrigin(originUrl.origin)) { return `${originUrl.protocol}//${originUrl.hostname}:${ADMIN_LOCAL_OIDC_PORT}/oidc`; } } catch { return ADMIN_DEFAULT_PRODUCTION_OIDC_AUTHORITY; } return ADMIN_DEFAULT_PRODUCTION_OIDC_AUTHORITY; } export function canStartBrowserPkceLogin({ isSecureContext = window.isSecureContext, origin = window.location.origin, cryptoSubtleAvailable = Boolean(window.crypto?.subtle), }: BrowserPkceLoginCheck = {}) { if (!cryptoSubtleAvailable) { return false; } if (isSecureContext) { return true; } return isDevTrustedPkceOrigin(origin); }