mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 05:06:55 +00:00
verify commands
This commit is contained in:
@@ -14,13 +14,16 @@ import { create } from "@zitadel/client";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||
import { User } from "@zitadel/proto/zitadel/user/v2/user_pb";
|
||||
import { headers } from "next/headers";
|
||||
import { getNextUrl } from "../client";
|
||||
import { getSessionCookieByLoginName } from "../cookies";
|
||||
import { checkMFAFactors } from "../verify-helper";
|
||||
import { createSessionAndUpdateCookie } from "./cookie";
|
||||
import { checkMFAFactors } from "./password";
|
||||
|
||||
type VerifyUserByEmailCommand = {
|
||||
userId: string;
|
||||
loginName?: string; // to determine already existing session
|
||||
organization?: string;
|
||||
code: string;
|
||||
isInvite: boolean;
|
||||
authRequestId?: string;
|
||||
@@ -39,82 +42,9 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
|
||||
return { error: "Could not verify user" };
|
||||
}
|
||||
|
||||
const userResponse = await getUserByID(command.userId);
|
||||
|
||||
if (!userResponse || !userResponse.user) {
|
||||
return { error: "Could not load user" };
|
||||
}
|
||||
|
||||
const checks = create(ChecksSchema, {
|
||||
user: {
|
||||
search: {
|
||||
case: "loginName",
|
||||
value: userResponse.user.preferredLoginName,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const session = await createSessionAndUpdateCookie(
|
||||
checks,
|
||||
undefined,
|
||||
command.authRequestId,
|
||||
);
|
||||
|
||||
const authMethodResponse = await listAuthenticationMethodTypes(
|
||||
command.userId,
|
||||
);
|
||||
|
||||
if (!authMethodResponse || !authMethodResponse.authMethodTypes) {
|
||||
return { error: "Could not load possible authenticators" };
|
||||
}
|
||||
// if no authmethods are found on the user, redirect to set one up
|
||||
if (
|
||||
authMethodResponse &&
|
||||
authMethodResponse.authMethodTypes &&
|
||||
authMethodResponse.authMethodTypes.length == 0
|
||||
) {
|
||||
const params = new URLSearchParams({
|
||||
sessionId: session.id,
|
||||
});
|
||||
|
||||
if (session.factors?.user?.loginName) {
|
||||
params.set("loginName", session.factors?.user?.loginName);
|
||||
}
|
||||
return { redirect: `/authenticator/set?${params}` };
|
||||
}
|
||||
}
|
||||
|
||||
type resendVerifyEmailCommand = {
|
||||
userId: string;
|
||||
isInvite: boolean;
|
||||
};
|
||||
|
||||
export async function resendVerification(command: resendVerifyEmailCommand) {
|
||||
return command.isInvite
|
||||
? resendInviteCode(command.userId)
|
||||
: resendEmailCode(command.userId);
|
||||
}
|
||||
|
||||
export type SendVerificationRedirectWithoutCheckCommand = {
|
||||
organization?: string;
|
||||
authRequestId?: string;
|
||||
} & (
|
||||
| { userId: string; loginName?: never }
|
||||
| { userId?: never; loginName: string }
|
||||
);
|
||||
|
||||
export async function sendVerificationRedirectWithoutCheck(
|
||||
command: SendVerificationRedirectWithoutCheckCommand,
|
||||
) {
|
||||
if (!("loginName" in command || "userId" in command)) {
|
||||
return { error: "No userId, nor loginname provided" };
|
||||
}
|
||||
|
||||
let session: Session | undefined;
|
||||
let user: User | undefined;
|
||||
|
||||
const loginSettings = await getLoginSettings(command.organization);
|
||||
|
||||
if ("loginName" in command) {
|
||||
const sessionCookie = await getSessionCookieByLoginName({
|
||||
loginName: command.loginName,
|
||||
@@ -147,10 +77,10 @@ export async function sendVerificationRedirectWithoutCheck(
|
||||
}
|
||||
|
||||
user = userResponse.user;
|
||||
} else if ("userId" in command) {
|
||||
} else {
|
||||
const userResponse = await getUserByID(command.userId);
|
||||
|
||||
if (!userResponse?.user) {
|
||||
if (!userResponse || !userResponse.user) {
|
||||
return { error: "Could not load user" };
|
||||
}
|
||||
|
||||
@@ -170,9 +100,6 @@ export async function sendVerificationRedirectWithoutCheck(
|
||||
undefined,
|
||||
command.authRequestId,
|
||||
);
|
||||
|
||||
// this is a fake error message to hide that the user does not even exist
|
||||
return { error: "Could not verify password" };
|
||||
}
|
||||
|
||||
if (!session?.factors?.user?.id) {
|
||||
@@ -187,6 +114,8 @@ export async function sendVerificationRedirectWithoutCheck(
|
||||
return { error: "Could not load user" };
|
||||
}
|
||||
|
||||
const loginSettings = await getLoginSettings(user.details?.resourceOwner);
|
||||
|
||||
const authMethodResponse = await listAuthenticationMethodTypes(user.userId);
|
||||
|
||||
if (!authMethodResponse || !authMethodResponse.authMethodTypes) {
|
||||
@@ -243,3 +172,163 @@ export async function sendVerificationRedirectWithoutCheck(
|
||||
|
||||
return { redirect: url };
|
||||
}
|
||||
|
||||
type resendVerifyEmailCommand = {
|
||||
userId: string;
|
||||
isInvite: boolean;
|
||||
authRequestId?: string;
|
||||
};
|
||||
|
||||
export async function resendVerification(command: resendVerifyEmailCommand) {
|
||||
const host = (await headers()).get("host");
|
||||
|
||||
return command.isInvite
|
||||
? resendInviteCode(command.userId)
|
||||
: resendEmailCode(command.userId, host, command.authRequestId);
|
||||
}
|
||||
|
||||
export type SendVerificationRedirectWithoutCheckCommand = {
|
||||
organization?: string;
|
||||
authRequestId?: string;
|
||||
} & (
|
||||
| { userId: string; loginName?: never }
|
||||
| { userId?: never; loginName: string }
|
||||
);
|
||||
|
||||
export async function sendVerificationRedirectWithoutCheck(
|
||||
command: SendVerificationRedirectWithoutCheckCommand,
|
||||
) {
|
||||
if (!("loginName" in command || "userId" in command)) {
|
||||
return { error: "No userId, nor loginname provided" };
|
||||
}
|
||||
|
||||
let session: Session | undefined;
|
||||
let user: User | undefined;
|
||||
|
||||
if ("loginName" in command) {
|
||||
const sessionCookie = await getSessionCookieByLoginName({
|
||||
loginName: command.loginName,
|
||||
organization: command.organization,
|
||||
}).catch((error) => {
|
||||
console.warn("Ignored error:", error);
|
||||
});
|
||||
|
||||
if (!sessionCookie) {
|
||||
return { error: "Could not load session cookie" };
|
||||
}
|
||||
|
||||
session = await getSession({
|
||||
sessionId: sessionCookie.id,
|
||||
sessionToken: sessionCookie.token,
|
||||
}).then((response) => {
|
||||
if (response?.session) {
|
||||
return response.session;
|
||||
}
|
||||
});
|
||||
|
||||
if (!session?.factors?.user?.id) {
|
||||
return { error: "Could not create session for user" };
|
||||
}
|
||||
|
||||
const userResponse = await getUserByID(session?.factors?.user?.id);
|
||||
|
||||
if (!userResponse?.user) {
|
||||
return { error: "Could not load user" };
|
||||
}
|
||||
|
||||
user = userResponse.user;
|
||||
} else if ("userId" in command) {
|
||||
const userResponse = await getUserByID(command.userId);
|
||||
|
||||
if (!userResponse?.user) {
|
||||
return { error: "Could not load user" };
|
||||
}
|
||||
|
||||
user = userResponse.user;
|
||||
|
||||
const checks = create(ChecksSchema, {
|
||||
user: {
|
||||
search: {
|
||||
case: "loginName",
|
||||
value: userResponse.user.preferredLoginName,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
session = await createSessionAndUpdateCookie(
|
||||
checks,
|
||||
undefined,
|
||||
command.authRequestId,
|
||||
);
|
||||
}
|
||||
|
||||
if (!session?.factors?.user?.id) {
|
||||
return { error: "Could not create session for user" };
|
||||
}
|
||||
|
||||
if (!session?.factors?.user?.id) {
|
||||
return { error: "Could not create session for user" };
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return { error: "Could not load user" };
|
||||
}
|
||||
|
||||
const authMethodResponse = await listAuthenticationMethodTypes(user.userId);
|
||||
|
||||
if (!authMethodResponse || !authMethodResponse.authMethodTypes) {
|
||||
return { error: "Could not load possible authenticators" };
|
||||
}
|
||||
|
||||
// if no authmethods are found on the user, redirect to set one up
|
||||
if (
|
||||
authMethodResponse &&
|
||||
authMethodResponse.authMethodTypes &&
|
||||
authMethodResponse.authMethodTypes.length == 0
|
||||
) {
|
||||
const params = new URLSearchParams({
|
||||
sessionId: session.id,
|
||||
});
|
||||
|
||||
if (session.factors?.user?.loginName) {
|
||||
params.set("loginName", session.factors?.user?.loginName);
|
||||
}
|
||||
return { redirect: `/authenticator/set?${params}` };
|
||||
}
|
||||
|
||||
const loginSettings = await getLoginSettings(user.details?.resourceOwner);
|
||||
|
||||
// redirect to mfa factor if user has one, or redirect to set one up
|
||||
checkMFAFactors(
|
||||
session,
|
||||
loginSettings,
|
||||
authMethodResponse.authMethodTypes,
|
||||
command.organization,
|
||||
command.authRequestId,
|
||||
);
|
||||
|
||||
// login user if no additional steps are required
|
||||
if (command.authRequestId && session.id) {
|
||||
const nextUrl = await getNextUrl(
|
||||
{
|
||||
sessionId: session.id,
|
||||
authRequestId: command.authRequestId,
|
||||
organization:
|
||||
command.organization ?? session.factors?.user?.organizationId,
|
||||
},
|
||||
loginSettings?.defaultRedirectUri,
|
||||
);
|
||||
|
||||
return { redirect: nextUrl };
|
||||
}
|
||||
|
||||
const url = await getNextUrl(
|
||||
{
|
||||
loginName: session.factors.user.loginName,
|
||||
organization: session.factors?.user?.organizationId,
|
||||
},
|
||||
loginSettings?.defaultRedirectUri,
|
||||
);
|
||||
|
||||
return { redirect: url };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user