From 4844731ee0e8a5bf8f99be0a4f30c95ce32a02b8 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 24 Jun 2025 15:29:58 +0200 Subject: [PATCH 01/12] saml post --- apps/login/src/app/login/route.ts | 21 +++++++++++++++++---- apps/login/src/lib/zitadel.ts | 1 - 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/apps/login/src/app/login/route.ts b/apps/login/src/app/login/route.ts index 0e181b76f1..0cf7f44a9c 100644 --- a/apps/login/src/app/login/route.ts +++ b/apps/login/src/app/login/route.ts @@ -215,11 +215,24 @@ export async function GET(request: NextRequest) { new URLSearchParams(params), }, }).then((resp) => { - if ( - resp.nextStep.value && - typeof resp.nextStep.value === "string" - ) { + if (resp.nextStep.case === "authUrl" && resp.nextStep.value) { return NextResponse.redirect(resp.nextStep.value); + } else if ( + resp.nextStep.case === "postForm" && + resp.nextStep.value + ) { + const postCall = resp.nextStep.value; + + const redirectUrl = constructUrl(request, "/saml-post"); + + redirectUrl.searchParams.set("url", url); + redirectUrl.searchParams.set("RelayState", postCall.relayState); + redirectUrl.searchParams.set( + "SAMLResponse", + postCall.samlResponse, + ); + + return NextResponse.redirect(redirectUrl.toString()); } }); } diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index e148e7c0be..f23b7edecf 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -962,7 +962,6 @@ export async function startIdentityProviderFlow({ urls, }: { serviceUrl: string; - idpId: string; urls: RedirectURLsJson; }) { From f7e272ace2f2a68cdb0de967f994c147278ecfe3 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 1 Jul 2025 09:55:50 +0200 Subject: [PATCH 02/12] post form --- apps/login/src/app/login/route.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/login/src/app/login/route.ts b/apps/login/src/app/login/route.ts index 79258f1baa..baaf594e5d 100644 --- a/apps/login/src/app/login/route.ts +++ b/apps/login/src/app/login/route.ts @@ -25,6 +25,7 @@ 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"; @@ -232,19 +233,17 @@ export async function GET(request: NextRequest) { if (resp.nextStep.case === "authUrl" && resp.nextStep.value) { return NextResponse.redirect(resp.nextStep.value); } else if ( - resp.nextStep.case === "postForm" && + resp.nextStep.case === "formData" && resp.nextStep.value ) { - const postCall = resp.nextStep.value; + const formData: FormData = resp.nextStep.value; const redirectUrl = constructUrl(request, "/saml-post"); - redirectUrl.searchParams.set("url", url); - redirectUrl.searchParams.set("RelayState", postCall.relayState); - redirectUrl.searchParams.set( - "SAMLResponse", - postCall.samlResponse, - ); + redirectUrl.searchParams.set("url", formData.url); + Object.entries(formData.fields).forEach(([k, v]) => { + redirectUrl.searchParams.set(k, v); + }); return NextResponse.redirect(redirectUrl.toString()); } From 00e2bddc6008428635678e5ad5027b0922c002c8 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 1 Jul 2025 10:59:43 +0200 Subject: [PATCH 03/12] 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({ From 8819be810b7e443c0406fc3e85389a9f51f88405 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 1 Jul 2025 11:01:06 +0200 Subject: [PATCH 04/12] cleanup --- apps/login/src/i18n/request.ts | 2 +- apps/login/src/lib/zitadel.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/login/src/i18n/request.ts b/apps/login/src/i18n/request.ts index 271d370f7c..9e5e37e231 100644 --- a/apps/login/src/i18n/request.ts +++ b/apps/login/src/i18n/request.ts @@ -16,7 +16,7 @@ export default getRequestConfig(async () => { const { serviceUrl } = getServiceUrlFromHeaders(_headers); const i18nOrganization = _headers.get("x-zitadel-i18n-organization") || ""; // You may need to set this header in middleware - console.log("i18nOrganization:", i18nOrganization); + let translations: JsonObject | {} = {}; try { const i18nJSON = await getHostedLoginTranslation({ diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index d836b3aa01..c2ec8c0922 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -91,7 +91,6 @@ export async function getHostedLoginTranslation({ {}, ) .then((resp) => { - console.log(resp); return resp.translations ? resp.translations : undefined; }); From 71162c4a6b4c9642c5b1be1ed8b28334608c99cf Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 1 Jul 2025 11:08:02 +0200 Subject: [PATCH 05/12] override relative url --- apps/login/src/app/login/route.ts | 9 ++++++--- apps/login/src/lib/zitadel.ts | 12 +++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/apps/login/src/app/login/route.ts b/apps/login/src/app/login/route.ts index 7a18c1fffa..db67efa229 100644 --- a/apps/login/src/app/login/route.ts +++ b/apps/login/src/app/login/route.ts @@ -217,7 +217,7 @@ export async function GET(request: NextRequest) { params.set("organization", organization); } - const url = await startIdentityProviderFlow({ + let url: string | null = await startIdentityProviderFlow({ serviceUrl, idpId, urls: { @@ -237,9 +237,12 @@ export async function GET(request: NextRequest) { ); } - const absoluteUrl = constructUrl(request, url); + if (url.startsWith("/")) { + // if the url is a relative path, construct the absolute url + url = constructUrl(request, url).toString(); + } - return NextResponse.redirect(absoluteUrl); + return NextResponse.redirect(url); } } } diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index c2ec8c0922..8a05701e97 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -985,16 +985,18 @@ export async function startIdentityProviderFlow({ 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"); + const redirectUrl = "/saml-post"; + + const params = new URLSearchParams({ url: formData.url }); - redirectUrl.searchParams.set("url", formData.url); Object.entries(formData.fields).forEach(([k, v]) => { - redirectUrl.searchParams.set(k, v); + params.append(k, v); }); - return redirectUrl.toString(); + return `${redirectUrl}?${params.toString()}`; + } else { + return null; } - return null; }); } From 48fd73952eef08c263bd481459a9a79ca96e04fa Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 1 Jul 2025 14:28:51 +0200 Subject: [PATCH 06/12] fix: acceptance --- .github/workflows/test.yml | 6 ++++++ acceptance/docker-compose.yaml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dac5fcee85..3764bd1058 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -93,6 +93,12 @@ jobs: uses: docker/setup-buildx-action@v3 if: ${{ matrix.command == 'test:acceptance' }} + - name: Build acceptance setup image + run: | + cd acceptance + docker build -t acceptance-setup:latest . + if: ${{ matrix.command == 'test:acceptance' }} + - name: Run ZITADEL run: ZITADEL_DEV_UID=root pnpm run-sink if: ${{ matrix.command == 'test:acceptance' }} diff --git a/acceptance/docker-compose.yaml b/acceptance/docker-compose.yaml index d033b1c39c..a68a435e83 100644 --- a/acceptance/docker-compose.yaml +++ b/acceptance/docker-compose.yaml @@ -41,7 +41,7 @@ services: setup: user: "${ZITADEL_DEV_UID}" container_name: setup - build: . + image: acceptance-setup:latest environment: PAT_FILE: /pat/zitadel-admin-sa.pat ZITADEL_API_INTERNAL_URL: http://zitadel:8080 From 1cbe7afb87731d269fad738cb148b5358c21d023 Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Tue, 1 Jul 2025 15:38:06 +0200 Subject: [PATCH 07/12] fix: use custom req headers in all server requests --- apps/login/next-env-vars.d.ts | 2 +- apps/login/src/lib/self.ts | 2 +- apps/login/src/lib/server/password.ts | 2 +- apps/login/src/lib/service.ts | 4 ++-- apps/login/src/lib/zitadel.ts | 23 +++++++++++++++++++++++ 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/apps/login/next-env-vars.d.ts b/apps/login/next-env-vars.d.ts index 691bfa6f56..b7a525858c 100644 --- a/apps/login/next-env-vars.d.ts +++ b/apps/login/next-env-vars.d.ts @@ -28,6 +28,6 @@ declare namespace NodeJS { * Optional: custom request headers to be added to every request * Split by comma, key value pairs separated by colon */ - CUSTOM_REQUEST_HEADERS: string; + CUSTOM_REQUEST_HEADERS?: string; } } diff --git a/apps/login/src/lib/self.ts b/apps/login/src/lib/self.ts index 7375f4f114..8d6f9aac55 100644 --- a/apps/login/src/lib/self.ts +++ b/apps/login/src/lib/self.ts @@ -1,6 +1,6 @@ "use server"; -import { createServerTransport } from "@zitadel/client/node"; +import { createServerTransport } from "./zitadel"; import { createUserServiceClient } from "@zitadel/client/v2"; import { headers } from "next/headers"; import { getSessionCookieById } from "./cookies"; diff --git a/apps/login/src/lib/server/password.ts b/apps/login/src/lib/server/password.ts index 3786145157..0ff31198fc 100644 --- a/apps/login/src/lib/server/password.ts +++ b/apps/login/src/lib/server/password.ts @@ -17,7 +17,7 @@ import { setUserPassword, } from "@/lib/zitadel"; import { ConnectError, create } from "@zitadel/client"; -import { createServerTransport } from "@zitadel/client/node"; +import { createServerTransport } from "../zitadel"; import { createUserServiceClient } from "@zitadel/client/v2"; import { Checks, diff --git a/apps/login/src/lib/service.ts b/apps/login/src/lib/service.ts index 0fbb083b05..bbf50c9fdc 100644 --- a/apps/login/src/lib/service.ts +++ b/apps/login/src/lib/service.ts @@ -1,5 +1,5 @@ import { createClientFor } from "@zitadel/client"; -import { createServerTransport } from "@zitadel/client/node"; +import { createServerTransport } from "./zitadel"; import { IdentityProviderService } from "@zitadel/proto/zitadel/idp/v2/idp_service_pb"; import { OIDCService } from "@zitadel/proto/zitadel/oidc/v2/oidc_service_pb"; import { OrganizationService } from "@zitadel/proto/zitadel/org/v2/org_service_pb"; @@ -50,7 +50,7 @@ export async function createServiceForHost( : [ (next) => { return (req) => { - process.env.CUSTOM_REQUEST_HEADERS.split(",").forEach( + process.env.CUSTOM_REQUEST_HEADERS!.split(",").forEach( (header) => { const kv = header.split(":"); req.header.set(kv[0], kv[1]); diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 8a05701e97..5b7ff041f3 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -52,6 +52,8 @@ import { import { unstable_cacheLife as cacheLife } from "next/cache"; import { getUserAgent } from "./fingerprint"; import { createServiceForHost } from "./service"; +import { createServerTransport as libCreateServerTransport } from "@zitadel/client/node"; +import { Transport } from '@connectrpc/connect'; const useCache = process.env.DEBUG !== "true"; @@ -1497,3 +1499,24 @@ export async function listAuthenticationMethodTypes({ userId, }); } + +export function createServerTransport(token: string, baseUrl: string): Transport { + return libCreateServerTransport(token, { + baseUrl, + interceptors: !process.env.CUSTOM_REQUEST_HEADERS + ? undefined + : [ + (next) => { + return (req) => { + process.env.CUSTOM_REQUEST_HEADERS!.split(",").forEach( + (header) => { + const kv = header.split(":"); + req.header.set(kv[0], kv[1]); + }, + ); + return next(req); + }; + }, + ], + }); +} From 816795f94919f1d91cbc6304f1b617b807b48c01 Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Tue, 1 Jul 2025 15:43:33 +0200 Subject: [PATCH 08/12] clean --- apps/login/src/lib/self.ts | 8 +------- apps/login/src/lib/server/password.ts | 4 +--- apps/login/src/lib/service.ts | 19 +------------------ 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/apps/login/src/lib/self.ts b/apps/login/src/lib/self.ts index 8d6f9aac55..8be9a27368 100644 --- a/apps/login/src/lib/self.ts +++ b/apps/login/src/lib/self.ts @@ -7,14 +7,8 @@ import { getSessionCookieById } from "./cookies"; import { getServiceUrlFromHeaders } from "./service-url"; import { getSession } from "./zitadel"; -const transport = async (serviceUrl: string, token: string) => { - return createServerTransport(token, { - baseUrl: serviceUrl, - }); -}; - const myUserService = async (serviceUrl: string, sessionToken: string) => { - const transportPromise = await transport(serviceUrl, sessionToken); + const transportPromise = await createServerTransport(sessionToken, serviceUrl); return createUserServiceClient(transportPromise); }; diff --git a/apps/login/src/lib/server/password.ts b/apps/login/src/lib/server/password.ts index 0ff31198fc..700c2f7b92 100644 --- a/apps/login/src/lib/server/password.ts +++ b/apps/login/src/lib/server/password.ts @@ -428,9 +428,7 @@ export async function checkSessionAndSetPassword({ }); } else { const transport = async (serviceUrl: string, token: string) => { - return createServerTransport(token, { - baseUrl: serviceUrl, - }); + return createServerTransport(token, serviceUrl); }; const myUserService = async (serviceUrl: string, sessionToken: string) => { diff --git a/apps/login/src/lib/service.ts b/apps/login/src/lib/service.ts index bbf50c9fdc..76fc178f67 100644 --- a/apps/login/src/lib/service.ts +++ b/apps/login/src/lib/service.ts @@ -43,24 +43,7 @@ export async function createServiceForHost( throw new Error("No token found"); } - const transport = createServerTransport(token, { - baseUrl: serviceUrl, - interceptors: !process.env.CUSTOM_REQUEST_HEADERS - ? undefined - : [ - (next) => { - return (req) => { - process.env.CUSTOM_REQUEST_HEADERS!.split(",").forEach( - (header) => { - const kv = header.split(":"); - req.header.set(kv[0], kv[1]); - }, - ); - return next(req); - }; - }, - ], - }); + const transport = createServerTransport(token, serviceUrl); return createClientFor(service)(transport); } From f0670d86321ef0c2fea4eb098d4b69e4d6586357 Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Tue, 1 Jul 2025 15:45:06 +0200 Subject: [PATCH 09/12] fmt --- apps/login/src/lib/self.ts | 8 +++++--- apps/login/src/lib/server/password.ts | 2 +- apps/login/src/lib/service.ts | 2 +- apps/login/src/lib/zitadel.ts | 25 ++++++++++++++----------- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/login/src/lib/self.ts b/apps/login/src/lib/self.ts index 8be9a27368..df8508c29e 100644 --- a/apps/login/src/lib/self.ts +++ b/apps/login/src/lib/self.ts @@ -1,14 +1,16 @@ "use server"; -import { createServerTransport } from "./zitadel"; import { createUserServiceClient } from "@zitadel/client/v2"; import { headers } from "next/headers"; import { getSessionCookieById } from "./cookies"; import { getServiceUrlFromHeaders } from "./service-url"; -import { getSession } from "./zitadel"; +import { createServerTransport, getSession } from "./zitadel"; const myUserService = async (serviceUrl: string, sessionToken: string) => { - const transportPromise = await createServerTransport(sessionToken, serviceUrl); + const transportPromise = await createServerTransport( + sessionToken, + serviceUrl, + ); return createUserServiceClient(transportPromise); }; diff --git a/apps/login/src/lib/server/password.ts b/apps/login/src/lib/server/password.ts index 700c2f7b92..5c6fb03aa5 100644 --- a/apps/login/src/lib/server/password.ts +++ b/apps/login/src/lib/server/password.ts @@ -17,7 +17,6 @@ import { setUserPassword, } from "@/lib/zitadel"; import { ConnectError, create } from "@zitadel/client"; -import { createServerTransport } from "../zitadel"; import { createUserServiceClient } from "@zitadel/client/v2"; import { Checks, @@ -39,6 +38,7 @@ import { checkPasswordChangeRequired, checkUserVerification, } from "../verify-helper"; +import { createServerTransport } from "../zitadel"; type ResetPasswordCommand = { loginName: string; diff --git a/apps/login/src/lib/service.ts b/apps/login/src/lib/service.ts index 76fc178f67..f7e81cc9d6 100644 --- a/apps/login/src/lib/service.ts +++ b/apps/login/src/lib/service.ts @@ -1,5 +1,4 @@ import { createClientFor } from "@zitadel/client"; -import { createServerTransport } from "./zitadel"; import { IdentityProviderService } from "@zitadel/proto/zitadel/idp/v2/idp_service_pb"; import { OIDCService } from "@zitadel/proto/zitadel/oidc/v2/oidc_service_pb"; import { OrganizationService } from "@zitadel/proto/zitadel/org/v2/org_service_pb"; @@ -8,6 +7,7 @@ import { SessionService } from "@zitadel/proto/zitadel/session/v2/session_servic import { SettingsService } from "@zitadel/proto/zitadel/settings/v2/settings_service_pb"; import { UserService } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; import { systemAPIToken } from "./api"; +import { createServerTransport } from "./zitadel"; type ServiceClass = | typeof IdentityProviderService diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 5b7ff041f3..549bf65577 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -1,4 +1,6 @@ +import { Transport } from "@connectrpc/connect"; import { Client, create, Duration } from "@zitadel/client"; +import { createServerTransport as libCreateServerTransport } from "@zitadel/client/node"; import { makeReqCtx } from "@zitadel/client/v2"; import { IdentityProviderService } from "@zitadel/proto/zitadel/idp/v2/idp_service_pb"; import { @@ -52,8 +54,6 @@ import { import { unstable_cacheLife as cacheLife } from "next/cache"; import { getUserAgent } from "./fingerprint"; import { createServiceForHost } from "./service"; -import { createServerTransport as libCreateServerTransport } from "@zitadel/client/node"; -import { Transport } from '@connectrpc/connect'; const useCache = process.env.DEBUG !== "true"; @@ -1500,20 +1500,23 @@ export async function listAuthenticationMethodTypes({ }); } -export function createServerTransport(token: string, baseUrl: string): Transport { +export function createServerTransport( + token: string, + baseUrl: string, +): Transport { return libCreateServerTransport(token, { baseUrl, interceptors: !process.env.CUSTOM_REQUEST_HEADERS - ? undefined - : [ + ? undefined + : [ (next) => { return (req) => { - process.env.CUSTOM_REQUEST_HEADERS!.split(",").forEach( - (header) => { - const kv = header.split(":"); - req.header.set(kv[0], kv[1]); - }, - ); + process.env + .CUSTOM_REQUEST_HEADERS!.split(",") + .forEach((header) => { + const kv = header.split(":"); + req.header.set(kv[0], kv[1]); + }); return next(req); }; }, From ab203a0bae405e58c27b44579807792e3bd886dd Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Tue, 1 Jul 2025 15:47:58 +0200 Subject: [PATCH 10/12] robust --- apps/login/src/lib/zitadel.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 549bf65577..f1ccb385d5 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -1515,7 +1515,11 @@ export function createServerTransport( .CUSTOM_REQUEST_HEADERS!.split(",") .forEach((header) => { const kv = header.split(":"); - req.header.set(kv[0], kv[1]); + if (kv.length === 2) { + req.header.set(kv[0].trim(), kv[1].trim()); + } else { + console.warn(`Skipping malformed header: ${header}`); + } }); return next(req); }; From 28d13262fbe9de310e2833b45ba7b3b6c5c01007 Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Tue, 1 Jul 2025 16:03:10 +0200 Subject: [PATCH 11/12] import --- apps/login/src/lib/zitadel.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index f1ccb385d5..53162abce8 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -1,4 +1,3 @@ -import { Transport } from "@connectrpc/connect"; import { Client, create, Duration } from "@zitadel/client"; import { createServerTransport as libCreateServerTransport } from "@zitadel/client/node"; import { makeReqCtx } from "@zitadel/client/v2"; @@ -1503,7 +1502,7 @@ export async function listAuthenticationMethodTypes({ export function createServerTransport( token: string, baseUrl: string, -): Transport { +) { return libCreateServerTransport(token, { baseUrl, interceptors: !process.env.CUSTOM_REQUEST_HEADERS From a634c60232a295ccb5323be0a12e9702000fcfba Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Tue, 1 Jul 2025 16:04:24 +0200 Subject: [PATCH 12/12] lint --- apps/login/src/lib/zitadel.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 53162abce8..483d4e4ac9 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -1499,10 +1499,7 @@ export async function listAuthenticationMethodTypes({ }); } -export function createServerTransport( - token: string, - baseUrl: string, -) { +export function createServerTransport(token: string, baseUrl: string) { return libCreateServerTransport(token, { baseUrl, interceptors: !process.env.CUSTOM_REQUEST_HEADERS