11import { Cookie } from "@/lib/cookies" ;
22import { sendLoginname , SendLoginnameCommand } from "@/lib/server/loginname" ;
3- import { createResponse , getLoginSettings } from "@/lib/zitadel" ;
3+ import { createResponse , getLoginSettings , listAuthenticationMethodTypes } from "@/lib/zitadel" ;
44import { create } from "@zitadel/client" ;
55import { CreateResponseRequestSchema } from "@zitadel/proto/zitadel/saml/v2/saml_service_pb" ;
66import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb" ;
@@ -9,6 +9,7 @@ import { NextRequest, NextResponse } from "next/server";
99import { v4 as uuidv4 } from "uuid" ;
1010import { constructUrl } from "./service-url" ;
1111import { isSessionValid } from "./session" ;
12+ import { checkMFAFactors } from "./verify-helper" ;
1213
1314type LoginWithSAMLAndSession = {
1415 serviceUrl : string ;
@@ -118,8 +119,37 @@ export async function loginWithSAMLAndSession({
118119 console . log ( "Session is valid:" , isValid ) ;
119120
120121 if ( ! isValid && selectedSession . factors ?. user ) {
122+ // Check if user has already authenticated via IDP but needs MFA
123+ if ( selectedSession . factors ?. intent ?. verifiedAt ) {
124+ console . log ( "User has IDP authentication, checking MFA factors..." ) ;
125+
126+ const methods = await listAuthenticationMethodTypes ( {
127+ serviceUrl,
128+ userId : selectedSession . factors . user . id ,
129+ } ) ;
130+
131+ const loginSettings = await getLoginSettings ( {
132+ serviceUrl,
133+ organization : selectedSession . factors ?. user ?. organizationId ,
134+ } ) ;
135+
136+ const mfaFactorCheck = await checkMFAFactors (
137+ serviceUrl ,
138+ selectedSession ,
139+ loginSettings ,
140+ methods . authMethodTypes ,
141+ selectedSession . factors ?. user ?. organizationId ,
142+ `saml_${ samlRequest } ` ,
143+ ) ;
144+
145+ if ( mfaFactorCheck ?. redirect ) {
146+ console . log ( "Redirecting to MFA:" , mfaFactorCheck . redirect ) ;
147+ const absoluteUrl = constructUrl ( request , mfaFactorCheck . redirect ) ;
148+ return NextResponse . redirect ( absoluteUrl . toString ( ) ) ;
149+ }
150+ }
151+
121152 // if the session is not valid anymore, we need to redirect the user to re-authenticate /
122- // TODO: handle IDP intent direcly if available
123153 const command : SendLoginnameCommand = {
124154 loginName : selectedSession . factors . user ?. loginName ,
125155 organization : selectedSession . factors ?. user ?. organizationId ,
@@ -129,8 +159,13 @@ export async function loginWithSAMLAndSession({
129159 const res = await sendLoginname ( command ) ;
130160
131161 if ( res && "redirect" in res && res ?. redirect ) {
132- const absoluteUrl = constructUrl ( request , res . redirect ) ;
133- return NextResponse . redirect ( absoluteUrl . toString ( ) ) ;
162+ // Check if the redirect URL is already a full URL
163+ if ( res . redirect . startsWith ( "http://" ) || res . redirect . startsWith ( "https://" ) ) {
164+ return NextResponse . redirect ( res . redirect ) ;
165+ } else {
166+ const absoluteUrl = constructUrl ( request , res . redirect ) ;
167+ return NextResponse . redirect ( absoluteUrl . toString ( ) ) ;
168+ }
134169 }
135170 }
136171
0 commit comments