Files
pedwfrontend/tests/phase21/admin-auth-foundation.test.cjs

437 lines
13 KiB
JavaScript

const assert = require("assert");
const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
const vm = require("vm");
const {
createRes,
respondErrorMock,
respondSuccessMock
} = require("./_shared.cjs");
const rootDir = path.resolve(__dirname, "..", "..");
const syntheticEnv = {
ADMIN_AUTH_SECRET: "synthetic-admin-credential-value-0001",
ADMIN_SESSION_SECRET: "synthetic-session-signing-value-0002",
NEXTAUTH_URL: "https://admin.test.local"
};
const fixedNow = () => Date.parse("2026-10-26T12:00:00.000Z");
const fixedNonce = () => Buffer.alloc(16, 7);
const loadAdminAuthModule = () => {
const filePath = path.join(rootDir, "lib", "admin", "adminAuth.js");
let source = fs.readFileSync(filePath, "utf8");
source = source.replace(/import[\s\S]*?from\s+"[^"]+";\n?/g, "");
source = source.replace(/export const\s+/g, "const ");
source += `
module.exports = {
ADMIN_SESSION_COOKIE,
ADMIN_SESSION_TTL_SECONDS,
ADMIN_PASSPHRASE_MAX_LENGTH,
validateAdminPassphrase,
issueAdminSession,
validateAdminSession,
createAdminSessionCookie,
createClearedAdminSessionCookie,
readAdminSessionCookie,
hasTrustedSameOrigin,
setAdminAuthNoStore
};`;
const context = {
module: { exports: {} },
exports: {},
require,
process,
Buffer,
URL,
Date,
encodeURIComponent,
decodeURIComponent,
...crypto
};
vm.runInNewContext(source, context, { filename: filePath });
return context.module.exports;
};
const loadHandler = (relativePath, injected) => {
const filePath = path.join(rootDir, relativePath);
let source = fs.readFileSync(filePath, "utf8");
source = source.replace(/import[\s\S]*?from\s+"[^"]+";\n?/g, "");
source = source.replace(
/export default async function\s+(\w+)\s*\(/,
"async function $1("
);
source += "\nmodule.exports.default = handler;\n";
const context = {
module: { exports: {} },
exports: {},
require,
process,
...injected
};
vm.runInNewContext(source, context, { filename: filePath });
return context.module.exports.default;
};
const tests = [];
const test = (name, fn) => tests.push({ name, fn });
test("correct administrative credential succeeds", () => {
const auth = loadAdminAuthModule();
assert.strictEqual(
auth.validateAdminPassphrase(syntheticEnv.ADMIN_AUTH_SECRET, {
env: syntheticEnv
}),
true
);
});
test("incorrect administrative credential fails", () => {
const auth = loadAdminAuthModule();
assert.strictEqual(
auth.validateAdminPassphrase("incorrect-synthetic-credential", {
env: syntheticEnv
}),
false
);
assert.strictEqual(
auth.validateAdminPassphrase(
"x".repeat(auth.ADMIN_PASSPHRASE_MAX_LENGTH + 1),
{ env: syntheticEnv }
),
false
);
});
test("missing, short, or reused configuration fails closed", () => {
const auth = loadAdminAuthModule();
assert.strictEqual(
auth.validateAdminPassphrase("anything", { env: {} }),
false
);
assert.strictEqual(
auth.issueAdminSession({
env: {
...syntheticEnv,
ADMIN_SESSION_SECRET: "short"
},
now: fixedNow,
nonce: fixedNonce
}),
null
);
assert.strictEqual(
auth.issueAdminSession({
env: {
...syntheticEnv,
ADMIN_SESSION_SECRET: syntheticEnv.ADMIN_AUTH_SECRET
},
now: fixedNow,
nonce: fixedNonce
}),
null
);
});
test("session signing and validation succeed with a deterministic clock", () => {
const auth = loadAdminAuthModule();
const token = auth.issueAdminSession({
env: syntheticEnv,
now: fixedNow,
nonce: fixedNonce
});
assert.match(token, /^v1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/);
assert.strictEqual(
auth.validateAdminSession(token, { env: syntheticEnv, now: fixedNow }),
true
);
});
test("tampered session fails validation", () => {
const auth = loadAdminAuthModule();
const token = auth.issueAdminSession({
env: syntheticEnv,
now: fixedNow,
nonce: fixedNonce
});
const tampered = token.slice(0, -1) + (token.endsWith("A") ? "B" : "A");
assert.strictEqual(
auth.validateAdminSession(tampered, {
env: syntheticEnv,
now: fixedNow
}),
false
);
});
test("expired session fails validation", () => {
const auth = loadAdminAuthModule();
const token = auth.issueAdminSession({
env: syntheticEnv,
now: fixedNow,
nonce: fixedNonce
});
const expiredNow = () =>
fixedNow() + (auth.ADMIN_SESSION_TTL_SECONDS + 1) * 1000;
assert.strictEqual(
auth.validateAdminSession(token, {
env: syntheticEnv,
now: expiredNow
}),
false
);
});
test("malformed and unsigned sessions fail validation", () => {
const auth = loadAdminAuthModule();
for (const value of [null, "", "unsigned", "v1.payload", "v2.a.b"]){
assert.strictEqual(
auth.validateAdminSession(value, {
env: syntheticEnv,
now: fixedNow
}),
false
);
}
});
test("login sets production secure cookie attributes and no-store headers", async () => {
const auth = loadAdminAuthModule();
const token = auth.issueAdminSession({
env: syntheticEnv,
now: fixedNow,
nonce: fixedNonce
});
const handler = loadHandler("pages/api/admin/auth/login.js", {
validateAdminPassphrase: () => true,
issueAdminSession: () => token,
hasTrustedSameOrigin: () => true,
createAdminSessionCookie: (value) =>
auth.createAdminSessionCookie(value, {
now: fixedNow,
production: true
}),
setAdminAuthNoStore: auth.setAdminAuthNoStore,
respondError: respondErrorMock,
respondSuccess: respondSuccessMock
});
const req = {
method: "POST",
headers: { origin: syntheticEnv.NEXTAUTH_URL },
body: { passphrase: syntheticEnv.ADMIN_AUTH_SECRET }
};
const res = createRes();
await handler(req, res);
const cookie = res.state.headers["set-cookie"];
assert.strictEqual(res.state.statusCode, 200);
assert.match(cookie, /^pedw_admin_session=/);
assert.match(cookie, /Max-Age=1200/);
assert.match(cookie, /Expires=/);
assert.match(cookie, /Path=\//);
assert.match(cookie, /HttpOnly/);
assert.match(cookie, /SameSite=Strict/);
assert.match(cookie, /Secure/);
assert.strictEqual(
res.state.headers["cache-control"],
"no-store, max-age=0"
);
assert.strictEqual(res.state.headers.pragma, "no-cache");
});
test("logout clears the cookie", async () => {
const auth = loadAdminAuthModule();
const handler = loadHandler("pages/api/admin/auth/logout.js", {
hasTrustedSameOrigin: () => true,
createClearedAdminSessionCookie: () =>
auth.createClearedAdminSessionCookie({ production: true }),
setAdminAuthNoStore: auth.setAdminAuthNoStore,
respondError: respondErrorMock,
respondSuccess: respondSuccessMock
});
const res = createRes();
await handler(
{ method: "POST", headers: { origin: syntheticEnv.NEXTAUTH_URL } },
res
);
const cookie = res.state.headers["set-cookie"];
assert.strictEqual(res.state.statusCode, 200);
assert.match(cookie, /^pedw_admin_session=;/);
assert.match(cookie, /Max-Age=0/);
assert.match(cookie, /Expires=Thu, 01 Jan 1970 00:00:00 GMT/);
assert.match(cookie, /HttpOnly/);
assert.match(cookie, /SameSite=Strict/);
assert.match(cookie, /Secure/);
});
test("session-status route reports only authentication state", async () => {
const auth = loadAdminAuthModule();
const handler = loadHandler("pages/api/admin/auth/session.js", {
readAdminSessionCookie: () => "synthetic-token",
validateAdminSession: () => true,
setAdminAuthNoStore: auth.setAdminAuthNoStore,
respondError: respondErrorMock,
respondSuccess: respondSuccessMock
});
const res = createRes();
await handler({ method: "GET", headers: {} }, res);
assert.deepStrictEqual(JSON.parse(JSON.stringify(res.state.jsonBody)), {
authenticated: true
});
const serialized = JSON.stringify(res.state.jsonBody);
assert.ok(!serialized.includes(syntheticEnv.ADMIN_AUTH_SECRET));
assert.ok(!serialized.includes(syntheticEnv.ADMIN_SESSION_SECRET));
});
test("invalid request methods are rejected", async () => {
const auth = loadAdminAuthModule();
const shared = {
hasTrustedSameOrigin: () => true,
validateAdminPassphrase: () => true,
issueAdminSession: () => "token",
createAdminSessionCookie: () => "cookie",
createClearedAdminSessionCookie: () => "cookie",
readAdminSessionCookie: () => "token",
validateAdminSession: () => true,
setAdminAuthNoStore: auth.setAdminAuthNoStore,
respondError: respondErrorMock,
respondSuccess: respondSuccessMock
};
for (const [route, method] of [
["pages/api/admin/auth/login.js", "GET"],
["pages/api/admin/auth/logout.js", "GET"],
["pages/api/admin/auth/session.js", "POST"]
]) {
const handler = loadHandler(route, shared);
const res = createRes();
await handler({ method, headers: {}, body: {} }, res);
assert.strictEqual(res.state.statusCode, 405);
assert.strictEqual(res.state.jsonBody.error.code, "METHOD_NOT_ALLOWED");
}
});
test("missing or invalid trusted origin rejects state-changing requests", async () => {
const auth = loadAdminAuthModule();
assert.strictEqual(
auth.hasTrustedSameOrigin(
{ headers: { origin: syntheticEnv.NEXTAUTH_URL } },
{ env: syntheticEnv }
),
true
);
const login = loadHandler("pages/api/admin/auth/login.js", {
hasTrustedSameOrigin: (req) =>
auth.hasTrustedSameOrigin(req, { env: syntheticEnv }),
validateAdminPassphrase: () => true,
issueAdminSession: () => "token",
createAdminSessionCookie: () => "cookie",
setAdminAuthNoStore: auth.setAdminAuthNoStore,
respondError: respondErrorMock,
respondSuccess: respondSuccessMock
});
const logout = loadHandler("pages/api/admin/auth/logout.js", {
hasTrustedSameOrigin: (req) =>
auth.hasTrustedSameOrigin(req, { env: syntheticEnv }),
createClearedAdminSessionCookie: () => "cookie",
setAdminAuthNoStore: auth.setAdminAuthNoStore,
respondError: respondErrorMock,
respondSuccess: respondSuccessMock
});
for (const handler of [login, logout]) {
for (const origin of [undefined, "https://attacker.test", "not-a-url"]) {
const res = createRes();
await handler(
{
method: "POST",
headers: origin ? { origin } : {},
body: { passphrase: syntheticEnv.ADMIN_AUTH_SECRET }
},
res
);
assert.strictEqual(res.state.statusCode, 403);
assert.strictEqual(res.state.jsonBody.error.code, "FORBIDDEN");
}
}
});
test("authentication foundation has no Prisma, CRM, or NextAuth dependency", () => {
const files = [
"lib/admin/adminAuth.js",
"pages/api/admin/auth/login.js",
"pages/api/admin/auth/logout.js",
"pages/api/admin/auth/session.js"
];
for (const relativePath of files) {
const source = fs.readFileSync(path.join(rootDir, relativePath), "utf8");
assert.doesNotMatch(source, /@prisma|Prisma|getPortalLogin|CRM|next-auth/i);
}
});
test("administrative session verification is independent of portal cookies", () => {
const auth = loadAdminAuthModule();
const token = auth.issueAdminSession({
env: syntheticEnv,
now: fixedNow,
nonce: fixedNonce
});
const req = {
headers: {
cookie: `next-auth.session-token=portal-token; ${auth.ADMIN_SESSION_COOKIE}=${encodeURIComponent(
token
)}`
}
};
const extracted = auth.readAdminSessionCookie(req);
assert.strictEqual(extracted, token);
assert.strictEqual(
auth.validateAdminSession(extracted, {
env: syntheticEnv,
now: fixedNow
}),
true
);
});
const run = async () => {
let passed = 0;
for (const currentTest of tests) {
await currentTest.fn();
passed += 1;
}
console.log(
`Administrative authentication foundation tests passed (${passed}/${tests.length}).`
);
};
module.exports = run;
if (require.main === module) {
run().catch((error) => {
console.error(error);
process.exit(1);
});
}