import type { Router } from 'vue-router' import type { NormalizedRedirectConfig } from './types/redirect' /** * Redirect utilities for handling post-authentication navigation */ /** * Get redirect URL from current route query params */ export function getRedirectUrl( router: Router, config: NormalizedRedirectConfig, ): string { const redirect = router.currentRoute.value.query[config.queryKey] as string return redirect || config.fallback } /** * Validate redirect URL is safe (prevents open redirect attacks) */ export function isValidRedirect( redirectUrl: string, allowedPaths?: RegExp[], ): boolean { // Null or empty check if (!redirectUrl) { return false } // Prevent redirects to external URLs (absolute URLs with protocol) if (redirectUrl.startsWith('http://') || redirectUrl.startsWith('https://')) { return false } // Prevent protocol-relative URLs if (redirectUrl.startsWith('//')) { return false } // Prevent javascript: and data: URLs if (redirectUrl.startsWith('javascript:') || redirectUrl.startsWith('data:')) { return false } // Ensure it starts with / if (!redirectUrl.startsWith('/')) { return false } // If allowed paths are specified, check against them if (allowedPaths && allowedPaths.length > 0) { return allowedPaths.some(pattern => pattern.test(redirectUrl)) } return true } /** * Perform redirect after login with security validation */ export async function performRedirect( router: Router, config: NormalizedRedirectConfig, ): Promise { const redirect = getRedirectUrl(router, config) console.log('[PerformRedirect] Current route query:', router.currentRoute.value.query) console.log('[PerformRedirect] Redirect URL:', redirect) console.log('[PerformRedirect] Config fallback:', config.fallback) // Always validate redirect URL for security if (redirect !== config.fallback && !isValidRedirect(redirect, config.allowedPaths)) { console.warn('[Auth] Invalid redirect URL detected, using fallback:', redirect) await router.push(config.fallback) return } console.log('[PerformRedirect] Redirecting to:', redirect) await router.push(redirect) } /** * Build query params for redirect to login */ export function buildLoginQuery( currentPath: string, config: NormalizedRedirectConfig, ): Record { if (!config.preserveRedirect) { return {} } // Validate the current path before storing it if (isValidRedirect(currentPath, config.allowedPaths)) { return { [config.queryKey]: currentPath } } return {} }