mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-25 08:42:16 +00:00
90 lines
2.9 KiB
TypeScript
90 lines
2.9 KiB
TypeScript
"use server";
|
|
|
|
import { getAllSessions } from "@/lib/cookies";
|
|
import { createLogger } from "@/lib/logger";
|
|
import { loginWithOIDCAndSession } from "@/lib/oidc";
|
|
import { loginWithSAMLAndSession } from "@/lib/saml";
|
|
import { getServiceConfig } from "@/lib/service-url";
|
|
import { listSessions, ServiceConfig } from "@/lib/zitadel";
|
|
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
|
import { headers } from "next/headers";
|
|
|
|
const logger = createLogger("auth-flow");
|
|
|
|
export interface AuthFlowParams {
|
|
sessionId: string;
|
|
requestId: string;
|
|
organization?: string;
|
|
}
|
|
|
|
async function loadSessions({ serviceConfig, ids }: { serviceConfig: ServiceConfig; ids: string[] }): Promise<Session[]> {
|
|
const response = await listSessions({ serviceConfig, ids: ids.filter((id: string | undefined) => !!id) });
|
|
|
|
return response?.sessions ?? [];
|
|
}
|
|
|
|
/**
|
|
* Server Action to complete authentication flow
|
|
* Complete OIDC/SAML authentication flow with session
|
|
* This is the shared logic for flow completion
|
|
* Returns either an error or a redirect URL for client-side navigation
|
|
*/
|
|
export async function completeAuthFlow(
|
|
command: AuthFlowParams,
|
|
): Promise<{ error: string } | { redirect: string } | { samlData: { url: string; fields: Record<string, string> } }> {
|
|
const { sessionId, requestId } = command;
|
|
|
|
const _headers = await headers();
|
|
const { serviceConfig } = getServiceConfig(_headers);
|
|
|
|
const sessionCookies = await getAllSessions();
|
|
const ids = sessionCookies.map((s) => s.id);
|
|
let sessions: Session[] = [];
|
|
|
|
if (ids && ids.length) {
|
|
sessions = await loadSessions({ serviceConfig, ids });
|
|
}
|
|
|
|
if (requestId.startsWith("oidc_")) {
|
|
// Complete OIDC flow
|
|
const result = await loginWithOIDCAndSession({
|
|
serviceConfig,
|
|
authRequest: requestId.replace("oidc_", ""),
|
|
sessionId,
|
|
sessions,
|
|
sessionCookies,
|
|
});
|
|
|
|
// Safety net - ensure we always return a valid object
|
|
if (!result || typeof result !== "object" || (!("redirect" in result) && !("error" in result))) {
|
|
logger.error("Auth flow: Invalid result from loginWithOIDCAndSession:", { result });
|
|
return { error: "Authentication completed but navigation failed" };
|
|
}
|
|
|
|
return result;
|
|
} else if (requestId.startsWith("saml_")) {
|
|
// Complete SAML flow
|
|
const result = await loginWithSAMLAndSession({
|
|
serviceConfig,
|
|
samlRequest: requestId.replace("saml_", ""),
|
|
sessionId,
|
|
sessions,
|
|
sessionCookies,
|
|
});
|
|
|
|
// Safety net - ensure we always return a valid object
|
|
if (
|
|
!result ||
|
|
typeof result !== "object" ||
|
|
(!("redirect" in result) && !("error" in result) && !("samlData" in result))
|
|
) {
|
|
logger.error("Auth flow: Invalid result from loginWithSAMLAndSession:", { result });
|
|
return { error: "Authentication completed but navigation failed" };
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
return { error: "Invalid request ID format" };
|
|
}
|