All checks were successful
Monorepo Pipeline / 🧪 Quality Assurance (push) Successful in 14m32s
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Successful in 17s
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Successful in 3m17s
Monorepo Pipeline / 🐳 Build Build-Base (push) Successful in 2m38s
Monorepo Pipeline / 🐳 Build Production Runtime (push) Successful in 21s
Monorepo Pipeline / 🚀 Release (push) Successful in 14m53s
88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { cookies } from "next/headers";
|
|
|
|
export async function GET(req: NextRequest) {
|
|
const cookieStore = await cookies();
|
|
const authCookieName =
|
|
process.env.AUTH_COOKIE_NAME || "mintel_gatekeeper_session";
|
|
const password = process.env.GATEKEEPER_PASSWORD || "mintel";
|
|
|
|
const session = cookieStore.get(authCookieName);
|
|
|
|
// 1. URL Parameter Bypass (for automated tests/staging)
|
|
const originalUrl = req.headers.get("x-forwarded-uri") || "/";
|
|
const host =
|
|
req.headers.get("x-forwarded-host") || req.headers.get("host") || "";
|
|
const proto = req.headers.get("x-forwarded-proto") || "https";
|
|
|
|
try {
|
|
const url = new URL(originalUrl, `${proto}://${host}`);
|
|
if (url.searchParams.get("gk_bypass") === password) {
|
|
// Remove the bypass parameter from the redirect URL
|
|
url.searchParams.delete("gk_bypass");
|
|
const cleanUrl = url.pathname + url.search;
|
|
const absoluteCleanUrl = `${proto}://${host}${cleanUrl}`;
|
|
|
|
const response = NextResponse.redirect(absoluteCleanUrl);
|
|
|
|
// Set the session cookie so the bypass is persistent
|
|
const isDev = process.env.NODE_ENV === "development";
|
|
const cookieDomain = process.env.COOKIE_DOMAIN;
|
|
const sessionValue = JSON.stringify({
|
|
identity: "Bypass",
|
|
timestamp: Date.now(),
|
|
});
|
|
|
|
response.cookies.set(authCookieName, sessionValue, {
|
|
httpOnly: true,
|
|
secure: !isDev,
|
|
path: "/",
|
|
maxAge: 30 * 24 * 60 * 60, // 30 days
|
|
sameSite: "lax",
|
|
...(cookieDomain ? { domain: cookieDomain } : {}),
|
|
});
|
|
|
|
return response;
|
|
}
|
|
} catch (e) {
|
|
// URL parsing failed, proceed with normal logic
|
|
}
|
|
|
|
let isAuthenticated = false;
|
|
let identity = "Guest";
|
|
|
|
if (session?.value) {
|
|
if (session.value === password) {
|
|
isAuthenticated = true;
|
|
} else {
|
|
try {
|
|
const payload = JSON.parse(session.value);
|
|
if (payload.identity) {
|
|
isAuthenticated = true;
|
|
identity = payload.identity;
|
|
}
|
|
} catch (e) {
|
|
// Fallback or old format
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isAuthenticated) {
|
|
return new NextResponse("OK", {
|
|
status: 200,
|
|
headers: {
|
|
"X-Auth-User": identity,
|
|
},
|
|
});
|
|
}
|
|
|
|
// Traefik ForwardAuth headers
|
|
const gatekeeperUrl =
|
|
process.env.NEXT_PUBLIC_BASE_URL || `${proto}://gatekeeper.${host}`;
|
|
const absoluteOriginalUrl = `${proto}://${host}${originalUrl}`;
|
|
|
|
const loginUrl = `${gatekeeperUrl}/login?redirect=${encodeURIComponent(absoluteOriginalUrl)}`;
|
|
|
|
return NextResponse.redirect(loginUrl);
|
|
}
|