feat(ap4): integrate nginx auth_request

This commit is contained in:
donghyeon-ka
2026-07-25 14:55:04 +09:00
parent 5ce47689a9
commit 357b7f927b
7 changed files with 123 additions and 26 deletions
+26 -9
View File
@@ -4,6 +4,9 @@ import { chromium } from "playwright-core";
const password = process.env.E2E_PASSWORD;
assert.ok(password, "E2E_PASSWORD must be set");
const edgeBaseUrl = "http://localhost:8088";
const edgeEntryUrl = `${edgeBaseUrl}/`;
async function completeKeycloakLogin(page) {
for (let attempt = 1; attempt <= 2; attempt += 1) {
await page.locator("#username").fill(
@@ -13,11 +16,11 @@ async function completeKeycloakLogin(page) {
await page.locator("#kc-login").click();
await page.waitForLoadState("domcontentloaded");
if (page.url() === "http://localhost:4180/edge/me") {
if (page.url() === edgeEntryUrl) {
return;
}
if (attempt === 1) {
await page.goto("http://localhost:4180/oauth2/start?rd=%2Fedge%2Fme");
await page.goto(`${edgeBaseUrl}/oauth2/start?rd=${encodeURIComponent(edgeEntryUrl)}`);
await page.waitForURL(/localhost:8080/u);
}
}
@@ -40,7 +43,7 @@ try {
const edgeResponsePromise = page.waitForResponse(
(response) =>
response.url() === "http://localhost:4180/edge/me" &&
response.url() === edgeEntryUrl &&
response.status() === 302,
);
const authorizationRequestPromise = page.waitForRequest((request) =>
@@ -48,7 +51,7 @@ try {
"/protocol/openid-connect/auth?approval_prompt=",
),
);
await page.goto("http://localhost:4180/edge/me");
await page.goto(edgeEntryUrl);
const unauthenticatedEdgeResponse = await edgeResponsePromise;
assert.equal(unauthenticatedEdgeResponse.status(), 302);
@@ -63,10 +66,10 @@ try {
const edgeIdentity = JSON.parse(await page.locator("body").innerText());
assert.equal(edgeIdentity.pattern, "AP4-edge-forward-auth");
assert.ok(edgeIdentity.user);
assert.equal(edgeIdentity.identityHeader, "X-Forwarded-User");
assert.equal(edgeIdentity.identityHeader, "X-Auth-Request-User");
const callbackRequest = browserRequests.find(({ url }) =>
url.startsWith("http://localhost:4180/oauth2/callback?"),
url.startsWith(`${edgeBaseUrl}/oauth2/callback?`),
);
assert.ok(callbackRequest);
assert.equal(callbackRequest.method, "GET");
@@ -78,7 +81,7 @@ try {
"the confidential token exchange must be server-to-server",
);
const cookies = await context.cookies("http://localhost:4180/");
const cookies = await context.cookies(edgeEntryUrl);
const sessionCookie = cookies.find((cookie) => cookie.name === "AP4_SESSION");
assert.ok(sessionCookie);
assert.equal(sessionCookie.httpOnly, true);
@@ -94,17 +97,31 @@ try {
assert.deepEqual(storage.sessionStorage, []);
assert.equal(storage.readableCookies.includes("AP4_SESSION"), false);
const externalAuthSubrequest = await fetch(`${edgeBaseUrl}/oauth2/auth`);
assert.equal(externalAuthSubrequest.status, 404);
const apiResponse = await fetch(`${edgeBaseUrl}/api/edge`, {
redirect: "manual",
});
assert.equal(apiResponse.status, 401);
assert.equal(apiResponse.headers.get("location"), null);
await assert.rejects(
fetch("http://localhost:4180/ping"),
"oauth2-proxy must not be published on the host",
);
const missingHeader = await fetch("http://localhost:8081/edge/me");
assert.equal(missingHeader.status, 401);
const directSpoof = await fetch("http://localhost:8081/edge/me", {
headers: { "X-Forwarded-User": "spoofed-admin" },
headers: { "X-Auth-Request-User": "spoofed-admin" },
});
assert.equal(directSpoof.status, 200);
const spoofedIdentity = await directSpoof.json();
assert.equal(spoofedIdentity.user, "spoofed-admin");
console.log(
"pattern4 oauth2-proxy verified: redirect, PKCE login, forwarded-user 200, direct spoof precondition",
"pattern4 nginx auth_request verified: internal subrequest, browser redirect, API 401, forwarded identity",
);
} finally {
await browser.close();