fix(confidence-engine): preserve external auth callback origin
This commit is contained in:
@@ -4,7 +4,22 @@ import { NextResponse } from "next/server";
|
||||
export async function GET(request) {
|
||||
const requestUrl = new URL(request.url);
|
||||
const code = requestUrl.searchParams.get("code");
|
||||
const response = NextResponse.redirect(new URL("/", requestUrl.origin));
|
||||
|
||||
// Derive redirect origin from proxy-forwarded headers when present,
|
||||
// falling back to the direct request origin for local/direct access.
|
||||
const forwardedHost = request.headers.get("x-forwarded-host");
|
||||
const forwardedProto = request.headers.get("x-forwarded-proto");
|
||||
let origin;
|
||||
|
||||
if (forwardedHost && forwardedProto) {
|
||||
// Nginx Proxy Manager (and similar proxies) set these headers.
|
||||
// x-forwarded-host may contain host:port or just hostname; use as-is.
|
||||
origin = `${forwardedProto}://${forwardedHost}`;
|
||||
} else {
|
||||
origin = requestUrl.origin;
|
||||
}
|
||||
|
||||
const response = NextResponse.redirect(new URL("/", origin));
|
||||
|
||||
if (code) {
|
||||
const supabase = createServerClient(
|
||||
|
||||
@@ -19,9 +19,47 @@ vi.mock("@/lib/config", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("@supabase/ssr", () => ({
|
||||
createServerClient: () => ({ auth: { getUser: () => mockGetUser() } }),
|
||||
createServerClient: () => ({
|
||||
auth: {
|
||||
getUser: () => mockGetUser(),
|
||||
exchangeCodeForSession: vi.fn().mockResolvedValue(undefined),
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
describe("auth callback redirect origin", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("uses forwarded host/proto for redirect when behind proxy", async () => {
|
||||
const { GET } = await import("@/app/auth/callback/route.js");
|
||||
|
||||
const request = new Request("http://0.0.0.0:3000/auth/callback?code=abc123", {
|
||||
headers: {
|
||||
"x-forwarded-host": "confidence.rdbcloud.co.uk",
|
||||
"x-forwarded-proto": "https",
|
||||
},
|
||||
});
|
||||
|
||||
const response = await GET(request);
|
||||
|
||||
expect(response.status).toBe(307);
|
||||
expect(response.headers.get("location")).toBe("https://confidence.rdbcloud.co.uk/");
|
||||
});
|
||||
|
||||
it("falls back to request origin when no forwarded headers", async () => {
|
||||
const { GET } = await import("@/app/auth/callback/route.js");
|
||||
|
||||
const request = new Request("http://localhost:3000/auth/callback?code=xyz");
|
||||
|
||||
const response = await GET(request);
|
||||
|
||||
expect(response.status).toBe(307);
|
||||
expect(response.headers.get("location")).toBe("http://localhost:3000/");
|
||||
});
|
||||
});
|
||||
|
||||
describe("authenticated product boundary", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
Reference in New Issue
Block a user