diff --git a/apps/login/src/components/idp-signin.tsx b/apps/login/src/components/idp-signin.tsx index aee4bc77883..f537a3d3ceb 100644 --- a/apps/login/src/components/idp-signin.tsx +++ b/apps/login/src/components/idp-signin.tsx @@ -1,7 +1,7 @@ "use client"; import { createNewSessionForIdp } from "@/lib/server/session"; -import { useRouter } from "next/navigation"; +import { redirect, useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import { Alert } from "./alert"; import { Spinner } from "./spinner"; @@ -35,8 +35,18 @@ export function IdpSignin({ }, authRequestId, }) - .catch((error) => { - setError(error.message); + .then((response) => { + if (response && "error" in response && response?.error) { + setError(response?.error); + return; + } + + if (response && "redirect" in response && response?.redirect) { + redirect(response.redirect); + } + }) + .catch(() => { + setError("An internal error occurred"); return; }) .finally(() => { diff --git a/apps/login/src/components/password-form.tsx b/apps/login/src/components/password-form.tsx index 8c715236491..8b511d4d3a5 100644 --- a/apps/login/src/components/password-form.tsx +++ b/apps/login/src/components/password-form.tsx @@ -5,7 +5,7 @@ import { create } from "@zitadel/client"; import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import { useTranslations } from "next-intl"; -import { useRouter } from "next/navigation"; +import { redirect, useRouter } from "next/navigation"; import { useState } from "react"; import { useForm } from "react-hook-form"; import { Alert, AlertType } from "./alert"; @@ -73,6 +73,10 @@ export function PasswordForm({ setError(response.error); return; } + + if (response && "redirect" in response && response.redirect) { + redirect(response.redirect); + } } async function resetPasswordAndContinue() { diff --git a/apps/login/src/components/register-form.tsx b/apps/login/src/components/register-form.tsx index 40dfe3c1ea4..a496669e05e 100644 --- a/apps/login/src/components/register-form.tsx +++ b/apps/login/src/components/register-form.tsx @@ -7,7 +7,7 @@ import { PasskeysType, } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import { useTranslations } from "next-intl"; -import { useRouter } from "next/navigation"; +import { redirect, useRouter } from "next/navigation"; import { useState } from "react"; import { FieldValues, useForm } from "react-hook-form"; import { Alert } from "./alert"; @@ -84,11 +84,15 @@ export function RegisterForm({ setLoading(false); }); - if (response && "error" in response) { + if (response && "error" in response && response.error) { setError(response.error); return; } + if (response && "redirect" in response && response.redirect) { + redirect(response.redirect); + } + return response; } diff --git a/apps/login/src/components/set-password-form.tsx b/apps/login/src/components/set-password-form.tsx index b194065d2a1..48e6021ad2e 100644 --- a/apps/login/src/components/set-password-form.tsx +++ b/apps/login/src/components/set-password-form.tsx @@ -11,6 +11,7 @@ import { create } from "@zitadel/client"; import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb"; import { useTranslations } from "next-intl"; +import { redirect } from "next/navigation"; import { useState } from "react"; import { FieldValues, useForm } from "react-hook-form"; import { Alert } from "./alert"; @@ -126,6 +127,14 @@ export function SetPasswordForm({ return; } + if ( + passwordResponse && + "redirect" in passwordResponse && + passwordResponse.redirect + ) { + redirect(passwordResponse.redirect); + } + return; } diff --git a/apps/login/src/components/set-register-password-form.tsx b/apps/login/src/components/set-register-password-form.tsx index 71fe089c7e2..321eb3ba2c2 100644 --- a/apps/login/src/components/set-register-password-form.tsx +++ b/apps/login/src/components/set-register-password-form.tsx @@ -9,6 +9,7 @@ import { import { registerUser } from "@/lib/server/register"; import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb"; import { useTranslations } from "next-intl"; +import { redirect } from "next/navigation"; import { useState } from "react"; import { FieldValues, useForm } from "react-hook-form"; import { Alert } from "./alert"; @@ -74,10 +75,14 @@ export function SetRegisterPasswordForm({ setLoading(false); }); - if (response && "error" in response) { + if (response && "error" in response && response.error) { setError(response.error); return; } + + if (response && "redirect" in response && response.redirect) { + redirect(response.redirect); + } } const { errors } = formState; diff --git a/apps/login/src/components/sign-in-with-idp.tsx b/apps/login/src/components/sign-in-with-idp.tsx index 6375c3e3746..d2e4186a418 100644 --- a/apps/login/src/components/sign-in-with-idp.tsx +++ b/apps/login/src/components/sign-in-with-idp.tsx @@ -6,7 +6,7 @@ import { IdentityProvider, IdentityProviderType, } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; -import { useRouter } from "next/navigation"; +import { redirect, useRouter } from "next/navigation"; import { ReactNode, useState } from "react"; import { Alert } from "./alert"; import { SignInWithApple } from "./idps/sign-in-with-apple"; @@ -62,7 +62,9 @@ export function SignInWithIdp({ setLoading(false); }); - return response; + if (response && "redirect" in response && response?.redirect) { + redirect(response.redirect); + } } return ( diff --git a/apps/login/src/lib/server/idp.ts b/apps/login/src/lib/server/idp.ts index 019b05ecbce..0c5d26d45c5 100644 --- a/apps/login/src/lib/server/idp.ts +++ b/apps/login/src/lib/server/idp.ts @@ -1,7 +1,6 @@ "use server"; import { startIdentityProviderFlow } from "@/lib/zitadel"; -import { redirect } from "next/navigation"; export type StartIDPFlowCommand = { idpId: string; @@ -22,7 +21,7 @@ export async function startIDPFlow(command: StartIDPFlowCommand) { response.nextStep.case === "authUrl" && response?.nextStep.value ) { - return redirect(response.nextStep.value); + return { redirect: response.nextStep.value }; } }); } diff --git a/apps/login/src/lib/server/password.ts b/apps/login/src/lib/server/password.ts index 63d9f4319ff..526c8c044aa 100644 --- a/apps/login/src/lib/server/password.ts +++ b/apps/login/src/lib/server/password.ts @@ -20,7 +20,6 @@ import { import { User, UserState } from "@zitadel/proto/zitadel/user/v2/user_pb"; import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; import { headers } from "next/headers"; -import { redirect } from "next/navigation"; import { getNextUrl } from "../client"; import { getSessionCookieByLoginName } from "../cookies"; @@ -155,13 +154,13 @@ export async function sendPassword(command: UpdateSessionCommand) { const factor = availableSecondFactors[0]; // if passwordless is other method, but user selected password as alternative, perform a login if (factor === AuthenticationMethodType.TOTP) { - return redirect(`/otp/time-based?` + params); + return { redirect: `/otp/time-based?` + params }; } else if (factor === AuthenticationMethodType.OTP_SMS) { - return redirect(`/otp/sms?` + params); + return { redirect: `/otp/sms?` + params }; } else if (factor === AuthenticationMethodType.OTP_EMAIL) { - return redirect(`/otp/email?` + params); + return { redirect: `/otp/email?` + params }; } else if (factor === AuthenticationMethodType.U2F) { - return redirect(`/u2f?` + params); + return { redirect: `/u2f?` + params }; } } else if (availableSecondFactors?.length >= 1) { const params = new URLSearchParams({ @@ -179,7 +178,7 @@ export async function sendPassword(command: UpdateSessionCommand) { ); } - return redirect(`/mfa?` + params); + return { redirect: `/mfa?` + params }; } else if (user.state === UserState.INITIAL) { const params = new URLSearchParams({ loginName: session.factors.user.loginName, @@ -196,7 +195,7 @@ export async function sendPassword(command: UpdateSessionCommand) { ); } - return redirect(`/password/change?` + params); + return { redirect: `/password/change?` + params }; } else if (command.forceMfa && !availableSecondFactors.length) { const params = new URLSearchParams({ loginName: session.factors.user.loginName, @@ -216,7 +215,7 @@ export async function sendPassword(command: UpdateSessionCommand) { } // TODO: provide a way to setup passkeys on mfa page? - return redirect(`/mfa/set?` + params); + return { redirect: `/mfa/set?` + params }; } // TODO: implement passkey setup @@ -255,7 +254,7 @@ export async function sendPassword(command: UpdateSessionCommand) { loginSettings?.defaultRedirectUri, ); - return redirect(nextUrl); + return { redirect: nextUrl }; } const loginSettings = await getLoginSettings( @@ -269,7 +268,7 @@ export async function sendPassword(command: UpdateSessionCommand) { loginSettings?.defaultRedirectUri, ); - return redirect(url); + return { redirect: url }; } export async function changePassword(command: { diff --git a/apps/login/src/lib/server/register.ts b/apps/login/src/lib/server/register.ts index fc37466a56f..d045f4c8bff 100644 --- a/apps/login/src/lib/server/register.ts +++ b/apps/login/src/lib/server/register.ts @@ -8,7 +8,6 @@ import { ChecksJson, ChecksSchema, } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; -import { redirect } from "next/navigation"; import { getNextUrl } from "../client"; type RegisterUserCommand = { @@ -71,7 +70,7 @@ export async function registerUser(command: RegisterUserCommand) { params.append("authRequestId", command.authRequestId); } - return redirect("/passkey/set?" + params); + return { redirect: "/passkey/set?" + params }; } else { const loginSettings = await getLoginSettings( session.factors.user.organizationId, @@ -91,6 +90,6 @@ export async function registerUser(command: RegisterUserCommand) { loginSettings?.defaultRedirectUri, ); - return redirect(url); + return { redirect: url }; } } diff --git a/apps/login/src/lib/server/session.ts b/apps/login/src/lib/server/session.ts index bb08b05d36a..d204e4beef7 100644 --- a/apps/login/src/lib/server/session.ts +++ b/apps/login/src/lib/server/session.ts @@ -67,7 +67,7 @@ export async function createNewSessionForIdp(options: CreateNewSessionCommand) { ); if (url) { - return redirect(url); + return { redirect: url }; } }