diff --git a/apps/login/src/app/login/route.ts b/apps/login/src/app/login/route.ts index dd91519ee4..123a6d12a2 100644 --- a/apps/login/src/app/login/route.ts +++ b/apps/login/src/app/login/route.ts @@ -39,7 +39,7 @@ const gotoAccounts = ({ requestId: string; organization?: string; }): NextResponse => { - const accountsUrl = new URL("/accounts", request.url); + const accountsUrl = constructUrl(request, "/accounts"); if (requestId) { accountsUrl.searchParams.set("requestId", requestId); @@ -66,6 +66,19 @@ async function loadSessions({ return response?.sessions ?? []; } +export function constructUrl(request: NextRequest, path: string) { + const forwardedHost = + request.headers.get("x-zitadel-forward-host") ?? + request.headers.get("host"); + const basePath = process.env.NEXT_PUBLIC_BASE_PATH || ""; + return new URL( + `${basePath}${path}`, + forwardedHost?.startsWith("http") + ? forwardedHost + : `https://${forwardedHost}`, + ); +} + const ORG_SCOPE_REGEX = /urn:zitadel:iam:org:id:([0-9]+)/; const ORG_DOMAIN_SCOPE_REGEX = /urn:zitadel:iam:org:domain:primary:(.+)/; // TODO: check regex for all domain character options const IDP_SCOPE_REGEX = /urn:zitadel:iam:org:idp:id:(.+)/; @@ -223,7 +236,7 @@ export async function GET(request: NextRequest) { } if (authRequest && authRequest.prompt.includes(Prompt.CREATE)) { - const registerUrl = new URL("/register", request.url); + const registerUrl = constructUrl(request, "/register"); if (authRequest.id) { registerUrl.searchParams.set("requestId", `oidc_${authRequest.id}`); } @@ -263,7 +276,7 @@ export async function GET(request: NextRequest) { const res = await sendLoginname(command); if (res && "redirect" in res && res?.redirect) { - const absoluteUrl = new URL(res.redirect, request.url); + const absoluteUrl = constructUrl(request, res.redirect); return NextResponse.redirect(absoluteUrl.toString()); } } catch (error) { @@ -271,7 +284,7 @@ export async function GET(request: NextRequest) { } } - const loginNameUrl = new URL("/loginname", request.url); + const loginNameUrl = constructUrl(request, "/loginname"); if (authRequest.id) { loginNameUrl.searchParams.set("requestId", `oidc_${authRequest.id}`); } @@ -398,7 +411,7 @@ export async function GET(request: NextRequest) { } } } else { - const loginNameUrl = new URL("/loginname", request.url); + const loginNameUrl = constructUrl(request, "/loginname"); loginNameUrl.searchParams.set("requestId", requestId); if (authRequest?.loginHint) { diff --git a/apps/login/src/lib/oidc.ts b/apps/login/src/lib/oidc.ts index fd74e57027..290b0ee7f1 100644 --- a/apps/login/src/lib/oidc.ts +++ b/apps/login/src/lib/oidc.ts @@ -1,3 +1,4 @@ +import { constructUrl } from "@/app/login/route"; import { Cookie } from "@/lib/cookies"; import { sendLoginname, SendLoginnameCommand } from "@/lib/server/loginname"; import { createCallback, getLoginSettings } from "@/lib/zitadel"; @@ -54,7 +55,7 @@ export async function loginWithOIDCandSession({ const res = await sendLoginname(command); if (res && "redirect" in res && res?.redirect) { - const absoluteUrl = new URL(res.redirect, request.url); + const absoluteUrl = constructUrl(request, res.redirect); return NextResponse.redirect(absoluteUrl.toString()); } } @@ -107,7 +108,7 @@ export async function loginWithOIDCandSession({ return NextResponse.redirect(loginSettings.defaultRedirectUri); } - const signedinUrl = new URL("/signedin", request.url); + const signedinUrl = constructUrl(request, "/signedin"); if (selectedSession.factors?.user?.loginName) { signedinUrl.searchParams.set( diff --git a/apps/login/src/lib/saml.ts b/apps/login/src/lib/saml.ts index d559c8e7df..b8241d7c8c 100644 --- a/apps/login/src/lib/saml.ts +++ b/apps/login/src/lib/saml.ts @@ -1,3 +1,4 @@ +import { constructUrl } from "@/app/login/route"; import { Cookie } from "@/lib/cookies"; import { sendLoginname, SendLoginnameCommand } from "@/lib/server/loginname"; import { createResponse, getLoginSettings } from "@/lib/zitadel"; @@ -52,7 +53,7 @@ export async function loginWithSAMLandSession({ const res = await sendLoginname(command); if (res && "redirect" in res && res?.redirect) { - const absoluteUrl = new URL(res.redirect, request.url); + const absoluteUrl = constructUrl(request, res.redirect); return NextResponse.redirect(absoluteUrl.toString()); } } @@ -105,7 +106,7 @@ export async function loginWithSAMLandSession({ return NextResponse.redirect(loginSettings.defaultRedirectUri); } - const signedinUrl = new URL("/signedin", request.url); + const signedinUrl = constructUrl(request, "/signedin"); if (selectedSession.factors?.user?.loginName) { signedinUrl.searchParams.set(