Files
Jyotisha/frontend/tests/admin-reauth.test.ts
Jesse_Chen 9d8c73561f
Staging Backend Quality Gate / validate (push) Failing after 7m30s
Staging Backend Quality Gate / publish (push) Has been skipped
test(deploy): integrate billing admin rollout checks
2026-08-06 20:15:50 +08:00

111 lines
4.3 KiB
TypeScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import {
authorizeAdminAccess,
HIGH_RISK_ADMIN_CHALLENGE_TTL_MS,
issueHighRiskAdminChallenge,
issueHighRiskAdminProof,
isSameOriginAdminMutation,
verifyHighRiskAdminChallenge,
verifyHighRiskAdminProof,
} from "../src/lib/admin/auth-policy.ts";
import type { IdentityUser } from "../src/modules/identity/contracts.ts";
const now = 1_786_000_000_000;
const context = {
userId: "11111111-1111-4111-8111-111111111111",
sessionId: "22222222-2222-4222-8222-222222222222",
permission: "admin.users.manage_roles" as const,
origin: "https://admin.staging.jyotisha.chat",
};
const sessionToken = "better-auth-session-token-held-server-side";
const proofSecret = "admin-proof-secret-held-only-by-the-server";
function user(): IdentityUser {
return {
id: context.userId,
email: "admin@example.com",
emailVerified: true,
name: "Admin",
image: null,
role: ["user"],
twoFactorEnabled: false,
};
}
test("email OTP challenge is short-lived and bound to the requested permission and session", () => {
const challenge = issueHighRiskAdminChallenge(context, proofSecret, sessionToken, now);
assert.equal(
verifyHighRiskAdminChallenge(challenge, context, proofSecret, sessionToken, now + 1_000),
true,
);
assert.equal(verifyHighRiskAdminChallenge(
challenge,
{ ...context, permission: "billing.products.publish" },
proofSecret,
sessionToken,
now + 1_000,
), false);
assert.equal(verifyHighRiskAdminChallenge(
challenge,
context,
proofSecret,
"rotated-session-token",
now + 1_000,
), false);
assert.equal(verifyHighRiskAdminChallenge(
challenge,
context,
proofSecret,
sessionToken,
now + HIGH_RISK_ADMIN_CHALLENGE_TTL_MS,
), false);
});
test("high-risk proof succeeds only for its live Better Auth session", () => {
const proof = issueHighRiskAdminProof(context, proofSecret, sessionToken, now);
assert.equal(verifyHighRiskAdminProof(proof, context, proofSecret, sessionToken, now + 1_000), true);
assert.equal(verifyHighRiskAdminProof(proof, { ...context, sessionId: "wrong-session" }, proofSecret, sessionToken, now + 1_000), false);
assert.equal(verifyHighRiskAdminProof(
proof,
{ ...context, permission: "billing.products.publish" },
proofSecret,
sessionToken,
now + 1_000,
), false);
assert.equal(verifyHighRiskAdminProof(proof, context, "wrong-server-secret-that-is-long-enough", sessionToken, now + 1_000), false);
assert.equal(verifyHighRiskAdminProof(proof, context, proofSecret, sessionToken, now + 300_000), false);
});
test("high-risk authorization rejects missing permission and cross-origin requests", () => {
assert.deepEqual(authorizeAdminAccess(user(), [], context.permission), { allowed: false, status: 403 });
assert.equal(isSameOriginAdminMutation(context.origin, `${context.origin}/api/admin/reauth`), true);
assert.equal(isSameOriginAdminMutation("https://evil.example", `${context.origin}/api/admin/reauth`), false);
assert.equal(isSameOriginAdminMutation(null, `${context.origin}/api/admin/reauth`), false);
});
test("reauth route consumes Better Auth email OTP and sets a scoped HttpOnly proof", () => {
const route = readFileSync(new URL("../src/app/api/admin/reauth/route.ts", import.meta.url), "utf8");
const modal = readFileSync(new URL("../src/components/admin/reason-action-modal.tsx", import.meta.url), "utf8");
assert.match(route, /sendVerificationOTP/);
assert.match(route, /verifyEmailOTP/);
assert.match(route, /type: "email-verification"/);
assert.match(route, /issueHighRiskAdminChallenge/);
assert.match(route, /verifyHighRiskAdminChallenge/);
assert.match(route, /HIGH_RISK_ADMIN_CHALLENGE_COOKIE/);
assert.match(route, /verifyHighRiskAdminChallenge[\s\S]*verifyEmailOTP/);
assert.match(route, /httpOnly: true/);
assert.match(route, /sameSite: "strict"/);
assert.match(route, /secure: true/);
assert.match(route, /path: "\/api\/admin"/);
assert.match(route, /adminProofSigningSecret\(\)/);
assert.doesNotMatch(route, /console\.|otp.*log|log.*otp/i);
assert.match(modal, /reauthPermission/);
assert.match(modal, /action: "request"/);
assert.match(modal, /action: "verify"/);
assert.match(modal, /邮箱验证码/);
});