mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-08 23:25:12 +00:00
fix(login): improve error classification (#11926)
Closes #11923 # Which Problems Are Solved Client-side gRPC errors (e.g. NotFound, InvalidArgument, PermissionDenied) were being surfaced as HTTP 500 Internal Server Errors, causing false SRE alerts and poor UI feedback. # How the Problems Are Solved - New transport interceptor (`error-classification.ts`): Automatically enriches every ConnectError with httpStatus and isUserError metadata via a `ClassifiedConnectError` wrapper - Route handler protection (`route.ts`, `flow-initiation.ts`): Catches classified errors from `getAuthRequest` / `getSAMLRequest` and returns correct HTTP status codes instead of 500 - Type safety: Replaced all magic number error.code === 9 checks with typed Code.FailedPrecondition + instanceof ConnectError across `oidc.ts`, `saml.ts`, `password.ts`, `zitadel.ts` - Classification-aware logging (`session.ts`): Client/user errors log at warn level, server errors at error level - Observability (`otel.ts`): Spans now include error.is_user_error and http.status_code attributes for alert filtering # Additional Changes Gitignore `next-env.d.ts`: This file is auto-generated by Next.js on every next dev and next build invocation. The two modes write slightly different import paths (.next/dev/types/ vs .next/types/), which causes git diff --exit-code to fail in CI whenever a developer runs next dev locally before committing. Since Next.js regenerates it automatically, there's no need to track it --------- Co-authored-by: Ramon <[email protected]> Co-authored-by: Copilot <[email protected]>
This commit is contained in:
co-authored by
Ramon
Copilot
parent
8e41d288ff
commit
ff4aae7b3f
@@ -1,6 +1,7 @@
|
||||
"use server";
|
||||
|
||||
import { getSessionCookieById } from "@/lib/cookies";
|
||||
import { isClassifiedError } from "@/lib/grpc/interceptors/error-classification";
|
||||
import { createLogger } from "@/lib/logger";
|
||||
import { getServiceConfig } from "@/lib/service-url";
|
||||
import {
|
||||
@@ -18,7 +19,7 @@ import {
|
||||
ServiceConfig,
|
||||
updateHuman,
|
||||
} from "@/lib/zitadel";
|
||||
import { Code, ConnectError, create } from "@zitadel/client";
|
||||
import { Code, create } from "@zitadel/client";
|
||||
import { AutoLinkingOption } from "@zitadel/proto/zitadel/idp/v2/idp_pb";
|
||||
import { OrganizationSchema } from "@zitadel/proto/zitadel/object/v2/object_pb";
|
||||
import {
|
||||
@@ -276,7 +277,7 @@ async function handleExplicitLinking(ctx: IDPHandlerContext): Promise<IDPHandler
|
||||
logger.error("Error linking IDP", { error });
|
||||
const errorMessage = error instanceof Error ? error.message : t("errors.unknownError");
|
||||
let params = buildRedirectParams({ error: errorMessage });
|
||||
if (error instanceof ConnectError && error.code === Code.AlreadyExists) {
|
||||
if (isClassifiedError(error) && error.code === Code.AlreadyExists) {
|
||||
params = buildRedirectParams({ error: "external_idp_taken" });
|
||||
}
|
||||
return { redirect: `/idp/${provider}/linking-failed?${params}` };
|
||||
|
||||
Reference in New Issue
Block a user