From 208a9eaa80245acc6cdd69acb8640054fbfb2970 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 6 Jan 2026 10:27:12 -0300 Subject: [PATCH] chore(auth): add error logging for saml-idp silent failures (#26484) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(auth): add error logging for saml-idp silent failures * chore(auth): add warn-level logging for saml-idp silent failures * chore(auth): change 'No user found' log to warn level * chore(auth): add warn-level logging for silent auth failures - saml-idp authorize: credentials, code, token, userInfo, user lookup - callbacks:signIn: account type, email, name, catch-all - callbacks:jwt: unknown account type (info → warn) - saml:profile: missing email from IdP - getServerSession: user not found for valid token --- .../features/auth/lib/getServerSession.ts | 2 +- .../features/auth/lib/next-auth-options.ts | 33 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/features/auth/lib/getServerSession.ts b/packages/features/auth/lib/getServerSession.ts index a06eab9ca4..903ed8ba7d 100644 --- a/packages/features/auth/lib/getServerSession.ts +++ b/packages/features/auth/lib/getServerSession.ts @@ -66,7 +66,7 @@ export async function getServerSession(options: { }); if (!userFromDb) { - log.debug("No user found"); + log.warn("No user found for valid token", { userId }); return null; } diff --git a/packages/features/auth/lib/next-auth-options.ts b/packages/features/auth/lib/next-auth-options.ts index 4ab888eed4..3c8b74cc06 100644 --- a/packages/features/auth/lib/next-auth-options.ts +++ b/packages/features/auth/lib/next-auth-options.ts @@ -336,6 +336,13 @@ if (isSAMLLoginEnabled) { }; }) => { log.debug("BoxyHQ:profile", safeStringify({ profile })); + if (!profile.email) { + log.warn("saml:profile - email missing from IdP response", { + hasFirstName: !!profile.firstName, + hasLastName: !!profile.lastName, + tenant: profile.requested?.tenant, + }); + } const userRepo = new UserRepository(prisma); const user = await userRepo.findByEmailAndIncludeProfilesAndPassword({ email: profile.email || "", @@ -371,12 +378,14 @@ if (isSAMLLoginEnabled) { async authorize(credentials): Promise { log.debug("CredentialsProvider:saml-idp:authorize", safeStringify({ credentials })); if (!credentials) { + log.warn("saml-idp:authorize - missing credentials object"); return null; } const { code } = credentials; if (!code) { + log.warn("saml-idp:authorize - missing code in credentials"); return null; } @@ -392,12 +401,14 @@ if (isSAMLLoginEnabled) { }); if (!access_token) { + log.warn("saml-idp:authorize - failed to obtain access_token from oauthController.token"); return null; } // Fetch user info const userInfo = await oauthController.userInfo(access_token); if (!userInfo) { + log.warn("saml-idp:authorize - failed to obtain userInfo from oauthController.userInfo"); return null; } @@ -426,7 +437,13 @@ if (isSAMLLoginEnabled) { }); } } - if (!user) throw new Error(ErrorCode.UserNotFound); + if (!user) { + log.warn("saml-idp:authorize - user not found and could not be auto-provisioned", { + emailDomain: email.split("@")[1], + hostedCal: Boolean(HOSTED_CAL_FEATURES), + }); + throw new Error(ErrorCode.UserNotFound); + } } const [userProfile] = user?.allProfiles ?? []; return { @@ -773,8 +790,8 @@ export const getOptions = ({ return await autoMergeIdentities(); } - log.info( - "callbacks:jwt:accountType:unknown", + log.warn( + "callbacks:jwt - unknown account type", safeStringify({ accountType: account.type, accountProvider: account.provider }) ); return token; @@ -845,14 +862,20 @@ export const getOptions = ({ } if (account?.type !== "oauth") { + log.warn("callbacks:signIn - unsupported account type for non-saml-idp provider", { + accountType: account?.type, + provider: account?.provider, + }); return false; } } if (!user.email) { + log.warn("callbacks:signIn - user email is missing", { provider: account?.provider }); return false; } if (!user.name) { + log.warn("callbacks:signIn - user name is missing", { emailDomain: user.email.split("@")[1], provider: account?.provider }); return false; } if (account?.provider) { @@ -1202,6 +1225,10 @@ export const getOptions = ({ } } + log.warn("callbacks:signIn - no matching provider or condition, denying access", { + provider: account?.provider, + accountType: account?.type, + }); return false; }, /**