randomayzer/src/lib/auth/app-config.ts

60 lines
2.9 KiB
TypeScript

/** Canonical origins are server configuration; request headers never choose them. */
function parseConfiguredUrl(value: string, name: string): URL {
let url: URL;
try { url = new URL(value); } catch { throw new Error(`FATAL CONFIGURATION ERROR: ${name} must be a valid URL.`); }
if (url.username || url.password || url.search || url.hash) {
throw new Error(`FATAL CONFIGURATION ERROR: ${name} cannot contain credentials, query or fragment.`);
}
return url;
}
export function isLocalSingleUserProfile(): boolean {
if (process.env.DEPLOYMENT_PROFILE !== 'local-single-user') return false;
const value = process.env.APP_BASE_URL?.trim();
if (!value) throw new Error('FATAL CONFIGURATION ERROR: APP_BASE_URL is required for local-single-user.');
const url = parseConfiguredUrl(value, 'APP_BASE_URL');
if (!['localhost', '127.0.0.1', '[::1]'].includes(url.hostname) || url.protocol !== 'http:' || url.pathname !== '/') {
throw new Error('FATAL CONFIGURATION ERROR: local-single-user requires an HTTP loopback origin.');
}
return true;
}
export function getAppBaseUrl(): string {
const envUrl = process.env.APP_BASE_URL?.trim();
if (process.env.NODE_ENV === 'production') {
if (!envUrl) throw new Error('FATAL CONFIGURATION ERROR: APP_BASE_URL environment variable is strictly required in production.');
const url = parseConfiguredUrl(envUrl, 'APP_BASE_URL');
if (url.pathname !== '/' || (url.protocol !== 'https:' && !isLocalSingleUserProfile())) {
throw new Error('FATAL CONFIGURATION ERROR: APP_BASE_URL must be a valid HTTPS URL in production.');
}
// Validate explicitly selected local profile even when URL happens to use HTTPS.
if (process.env.DEPLOYMENT_PROFILE === 'local-single-user') isLocalSingleUserProfile();
return url.origin;
}
return (envUrl || 'http://localhost:3000').replace(/\/+$/, '');
}
export function getVkRedirectUri(): string {
const envUri = process.env.VK_REDIRECT_URI?.trim();
if (process.env.NODE_ENV === 'production') {
if (!envUri) throw new Error('FATAL CONFIGURATION ERROR: VK_REDIRECT_URI environment variable is strictly required in production.');
const url = parseConfiguredUrl(envUri, 'VK_REDIRECT_URI');
const base = getAppBaseUrl();
if (url.origin !== base || url.pathname !== '/api/auth/vk/callback') {
throw new Error('FATAL CONFIGURATION ERROR: VK_REDIRECT_URI must match the canonical origin and callback path.');
}
return url.href;
}
return envUri || `${getAppBaseUrl()}/api/auth/vk/callback`;
}
export function getSecureSessionCookieFlag(): boolean {
if (process.env.NODE_ENV !== 'production') return false;
if (process.env.DEPLOYMENT_PROFILE === 'local-single-user') return !isLocalSingleUserProfile();
return true;
}
export function getTrustedHost(): string {
// Production configuration failures must never fall back to a different trust boundary.
return new URL(getAppBaseUrl()).host.toLowerCase();
}