From 00e2bddc6008428635678e5ad5027b0922c002c8 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 1 Jul 2025 10:59:43 +0200 Subject: [PATCH] fix: cleanup start idp flow --- apps/login/src/app/login/route.ts | 32 ++++++++-------------- apps/login/src/lib/server/idp.ts | 16 +++++------ apps/login/src/lib/server/loginname.ts | 16 +++++++---- apps/login/src/lib/zitadel.ts | 38 ++++++++++++++++++++------ 4 files changed, 58 insertions(+), 44 deletions(-) diff --git a/apps/login/src/app/login/route.ts b/apps/login/src/app/login/route.ts index baaf594e5d..7a18c1fffa 100644 --- a/apps/login/src/app/login/route.ts +++ b/apps/login/src/app/login/route.ts @@ -25,7 +25,6 @@ import { import { CreateResponseRequestSchema } from "@zitadel/proto/zitadel/saml/v2/saml_service_pb"; import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb"; import { IdentityProviderType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; -import { FormData } from "@zitadel/proto/zitadel/user/v2/idp_pb"; import { headers } from "next/headers"; import { NextRequest, NextResponse } from "next/server"; import { DEFAULT_CSP } from "../../../constants/csp"; @@ -218,7 +217,7 @@ export async function GET(request: NextRequest) { params.set("organization", organization); } - return startIdentityProviderFlow({ + const url = await startIdentityProviderFlow({ serviceUrl, idpId, urls: { @@ -229,25 +228,18 @@ export async function GET(request: NextRequest) { `${origin}/idp/${provider}/failure?` + new URLSearchParams(params), }, - }).then((resp) => { - if (resp.nextStep.case === "authUrl" && resp.nextStep.value) { - return NextResponse.redirect(resp.nextStep.value); - } else if ( - resp.nextStep.case === "formData" && - resp.nextStep.value - ) { - const formData: FormData = resp.nextStep.value; - - const redirectUrl = constructUrl(request, "/saml-post"); - - redirectUrl.searchParams.set("url", formData.url); - Object.entries(formData.fields).forEach(([k, v]) => { - redirectUrl.searchParams.set(k, v); - }); - - return NextResponse.redirect(redirectUrl.toString()); - } }); + + if (!url) { + return NextResponse.json( + { error: "Could not start IDP flow" }, + { status: 500 }, + ); + } + + const absoluteUrl = constructUrl(request, url); + + return NextResponse.redirect(absoluteUrl); } } } diff --git a/apps/login/src/lib/server/idp.ts b/apps/login/src/lib/server/idp.ts index 1925fe43d6..87f88a7c32 100644 --- a/apps/login/src/lib/server/idp.ts +++ b/apps/login/src/lib/server/idp.ts @@ -74,22 +74,20 @@ export type StartIDPFlowCommand = { async function startIDPFlow(command: StartIDPFlowCommand) { const basePath = process.env.NEXT_PUBLIC_BASE_PATH ?? ""; - return startIdentityProviderFlow({ + const url = await startIdentityProviderFlow({ serviceUrl: command.serviceUrl, idpId: command.idpId, urls: { successUrl: `${command.host.includes("localhost") ? "http://" : "https://"}${command.host}${basePath}${command.successUrl}`, failureUrl: `${command.host.includes("localhost") ? "http://" : "https://"}${command.host}${basePath}${command.failureUrl}`, }, - }).then((response) => { - if ( - response && - response.nextStep.case === "authUrl" && - response?.nextStep.value - ) { - return { redirect: response.nextStep.value }; - } }); + + if (!url) { + return { error: "Could not start IDP flow" }; + } + + return { redirect: url }; } type CreateNewSessionCommand = { diff --git a/apps/login/src/lib/server/loginname.ts b/apps/login/src/lib/server/loginname.ts index fa75929702..68cb345c06 100644 --- a/apps/login/src/lib/server/loginname.ts +++ b/apps/login/src/lib/server/loginname.ts @@ -102,7 +102,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { const basePath = process.env.NEXT_PUBLIC_BASE_PATH ?? ""; - const resp = await startIdentityProviderFlow({ + const url = await startIdentityProviderFlow({ serviceUrl, idpId: identityProviders[0].id, urls: { @@ -115,9 +115,11 @@ export async function sendLoginname(command: SendLoginnameCommand) { }, }); - if (resp?.nextStep.case === "authUrl") { - return { redirect: resp.nextStep.value }; + if (!url) { + return { error: "Could not start IDP flow" }; } + + return { redirect: url }; } }; @@ -166,7 +168,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { const basePath = process.env.NEXT_PUBLIC_BASE_PATH ?? ""; - const resp = await startIdentityProviderFlow({ + const url = await startIdentityProviderFlow({ serviceUrl, idpId: idp.id, urls: { @@ -179,9 +181,11 @@ export async function sendLoginname(command: SendLoginnameCommand) { }, }); - if (resp?.nextStep.case === "authUrl") { - return { redirect: resp.nextStep.value }; + if (!url) { + return { error: "Could not start IDP flow" }; } + + return { redirect: url }; } }; diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index c5f72266b9..d836b3aa01 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -23,7 +23,10 @@ import { import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import { SettingsService } from "@zitadel/proto/zitadel/settings/v2/settings_service_pb"; import { SendEmailVerificationCodeSchema } from "@zitadel/proto/zitadel/user/v2/email_pb"; -import type { RedirectURLsJson } from "@zitadel/proto/zitadel/user/v2/idp_pb"; +import type { + FormData, + RedirectURLsJson, +} from "@zitadel/proto/zitadel/user/v2/idp_pb"; import { NotificationType, SendPasswordResetLinkSchema, @@ -964,19 +967,36 @@ export async function startIdentityProviderFlow({ serviceUrl: string; idpId: string; urls: RedirectURLsJson; -}) { +}): Promise { const userService: Client = await createServiceForHost( UserService, serviceUrl, ); - return userService.startIdentityProviderIntent({ - idpId, - content: { - case: "urls", - value: urls, - }, - }); + return userService + .startIdentityProviderIntent({ + idpId, + content: { + case: "urls", + value: urls, + }, + }) + .then((resp) => { + if (resp.nextStep.case === "authUrl" && resp.nextStep.value) { + return resp.nextStep.value; + } else if (resp.nextStep.case === "formData" && resp.nextStep.value) { + const formData: FormData = resp.nextStep.value; + const redirectUrl = new URL("/saml-post"); + + redirectUrl.searchParams.set("url", formData.url); + Object.entries(formData.fields).forEach(([k, v]) => { + redirectUrl.searchParams.set(k, v); + }); + + return redirectUrl.toString(); + } + return null; + }); } export async function startLDAPIdentityProviderFlow({