mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 06:42:59 +00:00
implement redirects from server
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
|
import { PasskeysType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
|
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { createSessionForUserIdAndUpdateCookie } from "../../utils/session";
|
import { createSessionForUserIdAndUpdateCookie } from "../../utils/session";
|
||||||
@@ -24,6 +26,8 @@ export async function sendLoginname(command: SendLoginnameCommand) {
|
|||||||
organizationId: command.organization,
|
organizationId: command.organization,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const loginSettings = await getLoginSettings(command.organization);
|
||||||
|
|
||||||
if (users.details?.totalResult == BigInt(1) && users.result[0].userId) {
|
if (users.details?.totalResult == BigInt(1) && users.result[0].userId) {
|
||||||
const userId = users.result[0].userId;
|
const userId = users.result[0].userId;
|
||||||
const session = await createSessionForUserIdAndUpdateCookie(
|
const session = await createSessionForUserIdAndUpdateCookie(
|
||||||
@@ -41,14 +45,102 @@ export async function sendLoginname(command: SendLoginnameCommand) {
|
|||||||
session.factors?.user?.id,
|
session.factors?.user?.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
if (!methods.authMethodTypes || !methods.authMethodTypes.length) {
|
||||||
authMethodTypes: methods.authMethodTypes,
|
throw Error(
|
||||||
sessionId: session.id,
|
"User has no available authentication methods. Contact your administrator to setup authentication for the requested user.",
|
||||||
factors: session.factors,
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
if (methods.authMethodTypes.length == 1) {
|
||||||
|
const method = methods.authMethodTypes[0];
|
||||||
|
switch (method) {
|
||||||
|
case AuthenticationMethodType.PASSWORD: // user has only password as auth method
|
||||||
|
const paramsPassword: any = {
|
||||||
|
loginName: session.factors?.user?.loginName,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: does this have to be checked in loginSettings.allowDomainDiscovery
|
||||||
|
|
||||||
|
if (command.organization || session.factors?.user?.organizationId) {
|
||||||
|
paramsPassword.organization =
|
||||||
|
command.organization ?? session.factors?.user?.organizationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
loginSettings?.passkeysType &&
|
||||||
|
loginSettings?.passkeysType === PasskeysType.ALLOWED
|
||||||
|
) {
|
||||||
|
paramsPassword.promptPasswordless = `true`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.authRequestId) {
|
||||||
|
paramsPassword.authRequestId = command.authRequestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect("/password?" + new URLSearchParams(paramsPassword));
|
||||||
|
case AuthenticationMethodType.PASSKEY: // AuthenticationMethodType.AUTHENTICATION_METHOD_TYPE_PASSKEY
|
||||||
|
const paramsPasskey: any = { loginName: command.loginName };
|
||||||
|
if (command.authRequestId) {
|
||||||
|
paramsPasskey.authRequestId = command.authRequestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.organization || session.factors?.user?.organizationId) {
|
||||||
|
paramsPasskey.organization =
|
||||||
|
command.organization ?? session.factors?.user?.organizationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect(
|
||||||
|
"/passkey/login?" + new URLSearchParams(paramsPasskey),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// prefer passkey in favor of other methods
|
||||||
|
if (methods.authMethodTypes.includes(AuthenticationMethodType.PASSKEY)) {
|
||||||
|
const passkeyParams: any = {
|
||||||
|
loginName: command.loginName,
|
||||||
|
altPassword: `${methods.authMethodTypes.includes(1)}`, // show alternative password option
|
||||||
|
};
|
||||||
|
|
||||||
|
if (command.authRequestId) {
|
||||||
|
passkeyParams.authRequestId = command.authRequestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.organization || session.factors?.user?.organizationId) {
|
||||||
|
passkeyParams.organization =
|
||||||
|
command.organization ?? session.factors?.user?.organizationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect("/passkey/login?" + new URLSearchParams(passkeyParams));
|
||||||
|
} else if (
|
||||||
|
methods.authMethodTypes.includes(AuthenticationMethodType.IDP)
|
||||||
|
) {
|
||||||
|
// TODO: redirect user to idp
|
||||||
|
} else if (
|
||||||
|
methods.authMethodTypes.includes(AuthenticationMethodType.PASSWORD)
|
||||||
|
) {
|
||||||
|
// user has no passkey setup and login settings allow passkeys
|
||||||
|
const paramsPasswordDefault: any = { loginName: command.loginName };
|
||||||
|
|
||||||
|
if (loginSettings?.passkeysType === 1) {
|
||||||
|
paramsPasswordDefault.promptPasswordless = `true`; // PasskeysType.PASSKEYS_TYPE_ALLOWED,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.authRequestId) {
|
||||||
|
paramsPasswordDefault.authRequestId = command.authRequestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.organization || session.factors?.user?.organizationId) {
|
||||||
|
paramsPasswordDefault.organization =
|
||||||
|
command.organization ?? session.factors?.user?.organizationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect(
|
||||||
|
"/password?" + new URLSearchParams(paramsPasswordDefault),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const loginSettings = await getLoginSettings(command.organization);
|
|
||||||
// TODO: check if allowDomainDiscovery has to be allowed too, to redirect to the register page
|
// TODO: check if allowDomainDiscovery has to be allowed too, to redirect to the register page
|
||||||
// user not found, check if register is enabled on organization
|
// user not found, check if register is enabled on organization
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { sendLoginname } from "@/lib/server/loginname";
|
import { sendLoginname } from "@/lib/server/loginname";
|
||||||
import {
|
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
LoginSettings,
|
|
||||||
PasskeysType,
|
|
||||||
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
|
||||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { ReactNode, useEffect, useState } from "react";
|
import { ReactNode, useEffect, useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
@@ -71,123 +67,6 @@ export default function UsernameForm({
|
|||||||
organization?: string,
|
organization?: string,
|
||||||
) {
|
) {
|
||||||
const response = await submitLoginName(values, organization);
|
const response = await submitLoginName(values, organization);
|
||||||
|
|
||||||
if (!response) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.authMethodTypes && response.authMethodTypes.length === 0) {
|
|
||||||
setError(
|
|
||||||
"User has no available authentication methods. Contact your administrator to setup authentication for the requested user.",
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.authMethodTypes.length == 1) {
|
|
||||||
const method = response.authMethodTypes[0];
|
|
||||||
switch (method) {
|
|
||||||
case AuthenticationMethodType.PASSWORD: // user has only password as auth method
|
|
||||||
const paramsPassword: any = {
|
|
||||||
loginName: response.factors?.user?.loginName,
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: does this have to be checked in loginSettings.allowDomainDiscovery
|
|
||||||
|
|
||||||
if (organization || response.factors?.user?.organizationId) {
|
|
||||||
paramsPassword.organization =
|
|
||||||
organization ?? response.factors?.user?.organizationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
loginSettings?.passkeysType &&
|
|
||||||
loginSettings?.passkeysType === PasskeysType.ALLOWED
|
|
||||||
) {
|
|
||||||
paramsPassword.promptPasswordless = `true`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (authRequestId) {
|
|
||||||
paramsPassword.authRequestId = authRequestId;
|
|
||||||
}
|
|
||||||
|
|
||||||
return router.push(
|
|
||||||
"/password?" + new URLSearchParams(paramsPassword),
|
|
||||||
);
|
|
||||||
case AuthenticationMethodType.PASSKEY: // AuthenticationMethodType.AUTHENTICATION_METHOD_TYPE_PASSKEY
|
|
||||||
const paramsPasskey: any = { loginName: values.loginName };
|
|
||||||
if (authRequestId) {
|
|
||||||
paramsPasskey.authRequestId = authRequestId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (organization || response.factors?.user?.organizationId) {
|
|
||||||
paramsPasskey.organization =
|
|
||||||
organization ?? response.factors?.user?.organizationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
return router.push(
|
|
||||||
"/passkey/login?" + new URLSearchParams(paramsPasskey),
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
const paramsPasskeyDefault: any = { loginName: values.loginName };
|
|
||||||
|
|
||||||
if (loginSettings?.passkeysType === 1) {
|
|
||||||
paramsPasskeyDefault.promptPasswordless = `true`; // PasskeysType.PASSKEYS_TYPE_ALLOWED,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (authRequestId) {
|
|
||||||
paramsPasskeyDefault.authRequestId = authRequestId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (organization || response.factors?.user?.organizationId) {
|
|
||||||
paramsPasskeyDefault.organization =
|
|
||||||
organization ?? response.factors?.user?.organizationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
return router.push(
|
|
||||||
"/password?" + new URLSearchParams(paramsPasskeyDefault),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// prefer passkey in favor of other methods
|
|
||||||
if (response.authMethodTypes.includes(2)) {
|
|
||||||
const passkeyParams: any = {
|
|
||||||
loginName: values.loginName,
|
|
||||||
altPassword: `${response.authMethodTypes.includes(1)}`, // show alternative password option
|
|
||||||
};
|
|
||||||
|
|
||||||
if (authRequestId) {
|
|
||||||
passkeyParams.authRequestId = authRequestId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (organization || response.factors?.user?.organizationId) {
|
|
||||||
passkeyParams.organization =
|
|
||||||
organization ?? response.factors?.user?.organizationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
return router.push(
|
|
||||||
"/passkey/login?" + new URLSearchParams(passkeyParams),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// user has no passkey setup and login settings allow passkeys
|
|
||||||
const paramsPasswordDefault: any = { loginName: values.loginName };
|
|
||||||
|
|
||||||
if (loginSettings?.passkeysType === 1) {
|
|
||||||
paramsPasswordDefault.promptPasswordless = `true`; // PasskeysType.PASSKEYS_TYPE_ALLOWED,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (authRequestId) {
|
|
||||||
paramsPasswordDefault.authRequestId = authRequestId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (organization || response.factors?.user?.organizationId) {
|
|
||||||
paramsPasswordDefault.organization =
|
|
||||||
organization ?? response.factors?.user?.organizationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
return router.push(
|
|
||||||
"/password?" + new URLSearchParams(paramsPasswordDefault),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user