Add SAML 2.0 as a second SSO protocol alongside OIDC under a unified authMode/ssoType model. SP flows via @node-saml/node-saml: AuthnRequest generation, ACS POST assertion handling, SP metadata export, and admin config test endpoint. Replay-protected via saml_state cookie (httpOnly, SameSite=Lax) matched against InResponseTo; wantAssertionsSigned enforced. - src/lib/auth/saml.js: SAML instance builder, X.509 cert formatter, claim pickers - 4 routes under src/app/api/auth/saml/: start, acs, metadata, test - settingsRepo: ssoType + saml* defaults; login/status routes dispatch by type - profile page: SSO protocol switcher, IdP metadata XML + cert uploaders - login page: dynamic SAML sign-in button; Header: SAML user badge
33 lines
1.1 KiB
JavaScript
33 lines
1.1 KiB
JavaScript
import { NextResponse } from "next/server";
|
|
import { cookies } from "next/headers";
|
|
import { getSettings } from "@/lib/localDb";
|
|
import { buildSamlAuthorizeUrl, getSamlBaseUrl, isSamlConfigured } from "@/lib/auth/saml.js";
|
|
import { shouldUseSecureCookie } from "@/lib/auth/dashboardSession";
|
|
|
|
export async function GET(request) {
|
|
const settings = await getSettings();
|
|
const origin = getSamlBaseUrl(request, settings);
|
|
try {
|
|
if (!isSamlConfigured(settings)) {
|
|
return NextResponse.redirect(new URL("/login?error=saml_not_configured", origin));
|
|
}
|
|
|
|
const { authorizeUrl, requestId } = await buildSamlAuthorizeUrl(request, settings);
|
|
|
|
const cookieStore = await cookies();
|
|
cookieStore.set("saml_state", requestId, {
|
|
httpOnly: true,
|
|
secure: shouldUseSecureCookie(request),
|
|
sameSite: "lax",
|
|
path: "/",
|
|
maxAge: 10 * 60,
|
|
});
|
|
|
|
return NextResponse.redirect(authorizeUrl);
|
|
} catch (error) {
|
|
return NextResponse.redirect(
|
|
new URL(`/login?error=${encodeURIComponent(error.message || "saml_start_failed")}`, origin)
|
|
);
|
|
}
|
|
}
|