mirror of
https://github.com/zitadel/zitadel.git
synced 2025-07-17 17:19:14 +00:00
fix(login): better error handling for saml cookie serialization (#10259)
Fixes issues where SAML identity provider authentication would fail silently, leaving users unable to complete the login flow through external SAML providers. changes `saml.ts`: - Enhanced [setSAMLFormCookie()](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) with proper error handling and logging - Improved [getSAMLFormCookie()](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) with detailed error reporting - Added cookie size validation and warnings changes `zitadel.ts`: - Enhanced [startIdentityProviderFlow()](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) with robust form data handling - Added detailed logging for protobuf object structure analysis - Implemented safe fallback serialization for complex objects - Added comprehensive error handling for JSON operations
This commit is contained in:
parent
d5d6d37a25
commit
14a5946db8
@ -25,29 +25,70 @@ export async function getSAMLFormUID() {
|
||||
|
||||
export async function setSAMLFormCookie(value: string): Promise<string> {
|
||||
const cookiesList = await cookies();
|
||||
|
||||
const uid = await getSAMLFormUID();
|
||||
|
||||
await cookiesList.set({
|
||||
name: uid,
|
||||
value: value,
|
||||
httpOnly: true,
|
||||
path: "/",
|
||||
maxAge: 5 * 60, // 5 minutes
|
||||
});
|
||||
try {
|
||||
// Check cookie size limits (typical limit is 4KB)
|
||||
if (value.length > 4000) {
|
||||
console.warn(
|
||||
`SAML form cookie value is large (${value.length} characters), may exceed browser limits`,
|
||||
);
|
||||
}
|
||||
|
||||
return uid;
|
||||
// Log the attempt
|
||||
console.log(
|
||||
`Setting SAML form cookie with uid: ${uid}, value length: ${value.length}`,
|
||||
);
|
||||
|
||||
await cookiesList.set({
|
||||
name: uid,
|
||||
value: value,
|
||||
httpOnly: true,
|
||||
path: "/",
|
||||
maxAge: 5 * 60, // 5 minutes
|
||||
});
|
||||
|
||||
// Note: We can't reliably verify immediately due to Next.js cookies API behavior
|
||||
// Instead, we'll rely on the getSAMLFormCookie function to detect failures
|
||||
console.log(`Successfully set SAML form cookie with uid: ${uid}`);
|
||||
|
||||
return uid;
|
||||
} catch (error) {
|
||||
console.error(`Failed to set SAML form cookie with uid: ${uid}`, {
|
||||
error,
|
||||
valueLength: value.length,
|
||||
uid,
|
||||
});
|
||||
throw new Error(
|
||||
`Failed to set SAML form cookie: ${error instanceof Error ? error.message : String(error)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function getSAMLFormCookie(uid: string): Promise<string | null> {
|
||||
const cookiesList = await cookies();
|
||||
|
||||
const cookie = cookiesList.get(uid);
|
||||
if (!cookie || !cookie.value) {
|
||||
try {
|
||||
const cookie = cookiesList.get(uid);
|
||||
|
||||
if (!cookie) {
|
||||
console.warn(`SAML form cookie not found for uid: ${uid}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!cookie.value) {
|
||||
console.warn(`SAML form cookie found but empty value for uid: ${uid}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Successfully retrieved SAML form cookie for uid: ${uid}, value length: ${cookie.value.length}`,
|
||||
);
|
||||
return cookie.value;
|
||||
} catch (error) {
|
||||
console.error(`Error retrieving SAML form cookie for uid: ${uid}`, error);
|
||||
return null;
|
||||
}
|
||||
|
||||
return cookie.value;
|
||||
}
|
||||
|
||||
export async function loginWithSAMLAndSession({
|
||||
|
@ -989,10 +989,72 @@ export async function startIdentityProviderFlow({
|
||||
const formData: FormData = resp.nextStep.value;
|
||||
const redirectUrl = "/saml-post";
|
||||
|
||||
const dataId = await setSAMLFormCookie(JSON.stringify(formData.fields));
|
||||
const params = new URLSearchParams({ url: formData.url, id: dataId });
|
||||
try {
|
||||
// Log the attempt with structure inspection
|
||||
console.log("Attempting to stringify formData.fields:", {
|
||||
fields: formData.fields,
|
||||
fieldsType: typeof formData.fields,
|
||||
fieldsKeys: Object.keys(formData.fields || {}),
|
||||
fieldsEntries: Object.entries(formData.fields || {}),
|
||||
});
|
||||
|
||||
return `${redirectUrl}?${params.toString()}`;
|
||||
const stringifiedFields = JSON.stringify(formData.fields);
|
||||
console.log(
|
||||
"Successfully stringified formData.fields, length:",
|
||||
stringifiedFields.length,
|
||||
);
|
||||
|
||||
// Check cookie size limits (typical limit is 4KB)
|
||||
if (stringifiedFields.length > 4000) {
|
||||
console.warn(
|
||||
`SAML form cookie value is large (${stringifiedFields.length} characters), may exceed browser limits`,
|
||||
);
|
||||
}
|
||||
|
||||
const dataId = await setSAMLFormCookie(stringifiedFields);
|
||||
const params = new URLSearchParams({ url: formData.url, id: dataId });
|
||||
|
||||
return `${redirectUrl}?${params.toString()}`;
|
||||
} catch (stringifyError) {
|
||||
console.error("Failed to stringify formData.fields:", {
|
||||
error: stringifyError,
|
||||
formDataFields: formData.fields,
|
||||
formDataUrl: formData.url,
|
||||
fieldsType: typeof formData.fields,
|
||||
fieldsConstructor: formData.fields?.constructor?.name,
|
||||
});
|
||||
|
||||
// Try to create a safe serialization by converting to plain object
|
||||
try {
|
||||
const safeFields: Record<string, string> = {};
|
||||
const fieldsObj = formData.fields || {};
|
||||
|
||||
// Convert each field to a string if it's not already
|
||||
for (const [key, value] of Object.entries(fieldsObj)) {
|
||||
safeFields[key] =
|
||||
typeof value === "string" ? value : String(value);
|
||||
}
|
||||
|
||||
console.log(
|
||||
"Using safe serialization for formData.fields:",
|
||||
safeFields,
|
||||
);
|
||||
|
||||
const safeStringified = JSON.stringify(safeFields);
|
||||
const dataId = await setSAMLFormCookie(safeStringified);
|
||||
const params = new URLSearchParams({
|
||||
url: formData.url,
|
||||
id: dataId,
|
||||
});
|
||||
|
||||
return `${redirectUrl}?${params.toString()}`;
|
||||
} catch (fallbackError) {
|
||||
console.error("Safe serialization also failed:", fallbackError);
|
||||
throw new Error(
|
||||
`Failed to serialize SAML form data: ${stringifyError instanceof Error ? stringifyError.message : String(stringifyError)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user