@@ -33,31 +33,51 @@ const kratos = new FrontendApi(
3333 * browser naturally follows redirects (no CORS surprises).
3434 */
3535export async function loginWithProvider ( provider : string , returnTo : string = "/" ) : Promise < void > {
36- async function getFlowWithAction ( ) : Promise < HasUi | null > {
36+ // Prefer reusing an existing Kratos login flow if the URL already contains ?flow=...
37+ // This preserves the original return_to (e.g., the Hydra login_challenge callback)
38+ console . log ( "STARTING LOGIN WITH PROVIDER" , provider , returnTo ) ;
39+ const url = new URL ( window . location . href ) ;
40+ const existingFlowId = url . searchParams . get ( "flow" ) ;
41+ console . log ( "existingFlowId" , existingFlowId ) ;
42+
43+ // For custom UI: read the existing flow using a no-credentials JSON request.
44+ // Do NOT send cookies on this request or Kratos will require a CSRF header and return 403.
45+ async function readExistingFlow ( flowId : string ) : Promise < HasUi | null > {
3746 try {
38- const { data } = await kratos . createBrowserLoginFlow ( ) ;
39- const f = data as unknown as HasUi ;
47+ const { data } = await kratos . getLoginFlow ( { id : flowId } ) ;
48+ const f = data as HasUi ;
4049 const hasAction = typeof f . ui ?. action === "string" && f . ui . action . length > 0 ;
4150 const hasId = typeof f . id === "string" && f . id . length > 0 ;
42- if ( hasAction || hasId ) return f ;
43- return null ;
44- } catch {
51+ return ( hasAction || hasId ) ? f : null ;
52+ } catch ( err ) {
53+ console . log ( "getLoginFlow error" , err ) ;
4554 return null ;
4655 }
4756 }
4857
49- let flow = await getFlowWithAction ( ) ;
50- if ( ! flow ) flow = await getFlowWithAction ( ) ;
58+ let flow : HasUi | null = null ;
59+
60+ // Try to load the existing flow first (if present in URL)
61+ if ( existingFlowId ) {
62+ try {
63+ console . log ( "readExistingFlow" , existingFlowId ) ;
64+ flow = await readExistingFlow ( existingFlowId ) ;
65+ } catch {
66+ console . log ( "readExistingFlow error" , existingFlowId ) ;
67+ }
68+ }
5169
70+ // If no existing flow, initialize one via browser endpoint so Kratos sets cookies & returns here with ?flow=
5271 if ( ! flow ) {
53- // As a last resort, navigate to the browser endpoint to let Kratos drive the flow
54- window . location . href = `${ kratosBase } /self-service/login/browser` ;
72+ const rt = returnTo && returnTo . length > 0 ? `?return_to= ${ encodeURIComponent ( returnTo ) } ` : "" ;
73+ window . location . href = `${ kratosBase } /self-service/login/browser${ rt } ` ;
5574 return ;
5675 }
5776
5877 const action = flow . ui ?. action ?? ( flow . id ? `${ kratosBase } /self-service/login?flow=${ flow . id } ` : "" ) ;
5978 if ( ! action ) {
60- window . location . href = `${ kratosBase } /self-service/login/browser` ;
79+ const rt = returnTo && returnTo . length > 0 ? `?return_to=${ encodeURIComponent ( returnTo ) } ` : "" ;
80+ window . location . href = `${ kratosBase } /self-service/login/browser${ rt } ` ;
6181 return ;
6282 }
6383 const method = ( flow . ui ?. method ?? "POST" ) . toUpperCase ( ) ;
0 commit comments