@@ -55,17 +55,6 @@ export default defineEventHandler(async event => {
5555 }
5656
5757 const query = getQuery ( event )
58- // Validate returnTo is a safe relative path (prevent open redirect)
59- const newURL = new URL ( query . returnTo ?. toString ( ) || '/' , clientUri )
60- const redirectPath = newURL . origin === clientUri ? newURL . pathname : '/'
61-
62- setCookie ( event , 'auth_return_to' , redirectPath , {
63- maxAge : 60 * 5 ,
64- httpOnly : true ,
65- // secure only if NOT in dev mode
66- secure : ! import . meta. dev ,
67- } )
68-
6958 const clientMetadata = getOauthClientMetadata ( )
7059 const session = await useServerSession ( event )
7160 const { stateStore, sessionStore } = useOAuthStorage ( session )
@@ -79,6 +68,25 @@ export default defineEventHandler(async event => {
7968 } )
8069
8170 if ( ! query . code ) {
71+ // Validate returnTo is a safe relative path (prevent open redirect)
72+ // Only set cookie on initial auth request, not the callback
73+ let redirectPath = '/'
74+ try {
75+ const clientOrigin = new URL ( clientUri ) . origin
76+ const returnToUrl = new URL ( query . returnTo ?. toString ( ) || '/' , clientUri )
77+ if ( returnToUrl . origin === clientOrigin ) {
78+ redirectPath = returnToUrl . pathname + returnToUrl . search + returnToUrl . hash
79+ }
80+ } catch {
81+ // Invalid URL, fall back to root
82+ }
83+
84+ setCookie ( event , 'auth_return_to' , redirectPath , {
85+ maxAge : 60 * 5 ,
86+ httpOnly : true ,
87+ // secure only if NOT in dev mode
88+ secure : ! import . meta. dev ,
89+ } )
8290 try {
8391 const handle = query . handle ?. toString ( )
8492 const create = query . create ?. toString ( )
0 commit comments