@@ -52,13 +52,13 @@ function normalizeRedirectUrl(rawRedirect) {
5252 try {
5353 const currentOrigin = window . location . origin
5454
55- // root -relative path ("/resources/pages/edit?id=...")
55+ // Root -relative path ("/resources/pages/edit?id=...")
5656 if ( rawRedirect . startsWith ( "/" ) ) {
5757 const url = new URL ( rawRedirect , currentOrigin )
5858 return url . pathname + url . search + url . hash
5959 }
6060
61- // absolute URL - validate protocol first
61+ // Absolute URL - validate protocol first
6262 if ( ! isValidHttpUrl ( rawRedirect ) ) {
6363 return null
6464 }
@@ -102,10 +102,11 @@ export function useLogin() {
102102 totp,
103103 }
104104
105- // Add returnUrl if exists in query param
106- const returnUrl = route . query . redirect ?. toString ( ) || null
107- if ( returnUrl ) {
108- payload . returnUrl = returnUrl
105+ // Add returnUrl if exists in query param, but sanitize it first
106+ const rawReturnUrl = route . query . redirect ?. toString ( ) || null
107+ const safeReturnUrl = rawReturnUrl ? normalizeRedirectUrl ( rawReturnUrl ) : null
108+ if ( safeReturnUrl ) {
109+ payload . returnUrl = safeReturnUrl
109110 }
110111
111112 const responseData =
@@ -122,7 +123,8 @@ export function useLogin() {
122123 // If backend forces password rotation, still apply locale before redirect
123124 if ( responseData . rotate_password && responseData . redirect ) {
124125 applyUserLocale ( responseData )
125- window . location . href = responseData . redirect
126+ const safeRedirect = normalizeRedirectUrl ( responseData . redirect . toString ( ) )
127+ window . location . href = safeRedirect || "/"
126128 return { success : true , rotate : true }
127129 }
128130
@@ -135,8 +137,10 @@ export function useLogin() {
135137 // Terms and conditions redirect (apply locale before navigating)
136138 if ( responseData . load_terms && responseData . redirect ) {
137139 applyUserLocale ( responseData )
138- window . location . href = responseData . redirect
139- return { success : true , redirect : responseData . redirect }
140+ const safeRedirect = normalizeRedirectUrl ( responseData . redirect . toString ( ) )
141+ const target = safeRedirect || "/"
142+ window . location . href = target
143+ return { success : true , redirect : target }
140144 }
141145
142146 // External redirect param (apply locale before navigating)
@@ -147,7 +151,6 @@ export function useLogin() {
147151 const safeRedirect = normalizeRedirectUrl ( rawRedirect )
148152
149153 if ( safeRedirect ) {
150- // Keep query params (e.g. "?id=/api/pages/6") intact on same origin
151154 // Full reload here is intentional so the full app shell is rebuilt.
152155 window . location . href = safeRedirect
153156 return { success : true }
@@ -157,7 +160,8 @@ export function useLogin() {
157160 // Fallback backend redirect (apply locale before navigating)
158161 if ( responseData . redirect ) {
159162 applyUserLocale ( responseData )
160- window . location . href = responseData . redirect
163+ const safeRedirect = normalizeRedirectUrl ( responseData . redirect . toString ( ) )
164+ window . location . href = safeRedirect || "/"
161165 return { success : true }
162166 }
163167
0 commit comments