From b9d4ca824f8d580830a372df63d6ce1a7500279d Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Mon, 27 Jan 2025 16:23:46 +0100 Subject: [PATCH] error handler --- apps/login/src/lib/server/cookie.ts | 32 +++++++++++++++++---------- apps/login/src/lib/server/password.ts | 14 ++++++++++-- packages/zitadel-client/src/index.ts | 1 + 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/apps/login/src/lib/server/cookie.ts b/apps/login/src/lib/server/cookie.ts index 795a41cd8d6..32b39d6e9af 100644 --- a/apps/login/src/lib/server/cookie.ts +++ b/apps/login/src/lib/server/cookie.ts @@ -7,9 +7,10 @@ import { getSession, setSession, } from "@/lib/zitadel"; -import { Duration, timestampMs } from "@zitadel/client"; +import { ConnectError, Duration, timestampMs } from "@zitadel/client"; import { CredentialsCheckError, + CredentialsCheckErrorSchema, ErrorDetail, } from "@zitadel/proto/zitadel/message_pb"; import { @@ -30,13 +31,29 @@ type CustomCookieData = { authRequestId?: string; // if its linked to an OIDC flow }; +const passwordAttemptsHandler = (error: ConnectError) => { + const details = error.findDetails(CredentialsCheckErrorSchema); + + if (details[0] && "failedAttempts" in details[0]) { + const failedAttempts = details[0].failedAttempts; + throw { + error: `Failed to authenticate: You had ${failedAttempts} password attempts.`, + failedAttempts: failedAttempts, + }; + } + throw error; +}; + export async function createSessionAndUpdateCookie( checks: Checks, challenges: RequestChallenges | undefined, authRequestId: string | undefined, lifetime?: Duration, ): Promise { - const createdSession = await createSessionFromChecks(checks, challenges); + const createdSession = await createSessionFromChecks( + checks, + challenges, + ).catch(passwordAttemptsHandler); if (createdSession) { return getSession({ @@ -215,14 +232,5 @@ export async function setSessionAndUpdateCookie( throw "Session not be set"; } }) - .catch((error: ErrorDetail | CredentialsCheckError) => { - console.error("Could not set session", error); - if ("failedAttempts" in error && error.failedAttempts) { - throw { - error: `Failed to authenticate: You had ${error.failedAttempts} password attempts.`, - failedAttempts: error.failedAttempts, - }; - } - throw error; - }); + .catch(passwordAttemptsHandler); } diff --git a/apps/login/src/lib/server/password.ts b/apps/login/src/lib/server/password.ts index d69074aca3c..2f8afd87a2a 100644 --- a/apps/login/src/lib/server/password.ts +++ b/apps/login/src/lib/server/password.ts @@ -113,7 +113,12 @@ export async function sendPassword(command: UpdateSessionCommand) { ); return { - error: `Failed to authenticate: You had ${error.failedAttempts} of ${lockoutSettings?.maxPasswordAttempts} password attempts.`, + error: + `Failed to authenticate. You had ${error.failedAttempts} of ${lockoutSettings?.maxPasswordAttempts} password attempts.` + + (lockoutSettings?.maxPasswordAttempts && + error.failedAttempts >= lockoutSettings?.maxPasswordAttempts + ? "Contact your administrator to unlock your account" + : ""), }; } return { error: "Could not create session for user" }; @@ -136,7 +141,12 @@ export async function sendPassword(command: UpdateSessionCommand) { const lockoutSettings = await getLockoutSettings(command.organization); return { - error: `Failed to authenticate: You had ${error.failedAttempts} of ${lockoutSettings?.maxPasswordAttempts} password attempts.`, + error: + `Failed to authenticate. You had ${error.failedAttempts} of ${lockoutSettings?.maxPasswordAttempts} password attempts.` + + (lockoutSettings?.maxPasswordAttempts && + error.failedAttempts >= lockoutSettings?.maxPasswordAttempts + ? " Contact your administrator to unlock your account" + : ""), }; } throw error; diff --git a/packages/zitadel-client/src/index.ts b/packages/zitadel-client/src/index.ts index 64c3af50508..4d50003d7a6 100644 --- a/packages/zitadel-client/src/index.ts +++ b/packages/zitadel-client/src/index.ts @@ -6,3 +6,4 @@ export { create, fromJson, toJson } from "@bufbuild/protobuf"; export type { JsonObject } from "@bufbuild/protobuf"; export { TimestampSchema, timestampDate, timestampFromDate, timestampFromMs, timestampMs } from "@bufbuild/protobuf/wkt"; export type { Duration, Timestamp } from "@bufbuild/protobuf/wkt"; +export type { Code, ConnectError } from "@connectrpc/connect";