fix(ancpi): use full OpenAM login URL with module + goto params

OpenAM requires module=SelfRegistration and goto= redirect URL.
Also handle 302 manually to capture iPlanetDirectoryPro cookie,
then follow redirect to ePay for JSESSIONID.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-23 00:27:54 +02:00
parent b61cd71044
commit 259f56396b
+56 -21
View File
@@ -127,39 +127,74 @@ export class EpayClient {
/* ── Auth ───────────────────────────────────────────────────── */
private async login(): Promise<void> {
// Full login URL with module + goto params (required by OpenAM)
const loginUrlFull = `${LOGIN_URL}?module=SelfRegistration&goto=${encodeURIComponent("http://epay.ancpi.ro:80/epay/LogIn.action")}`;
const body = `IDToken1=${encodeURIComponent(this.username)}&IDToken2=${encodeURIComponent(this.password)}`;
const response = await this.client.post(LOGIN_URL, body, {
headers: { "Content-Type": "application/x-www-form-urlencoded" },
// Step 1: POST login — don't follow redirects so we capture cookies
const response = await this.client.post(loginUrlFull, body, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Referer: loginUrlFull,
},
timeout: DEFAULT_TIMEOUT_MS,
maxRedirects: 10,
validateStatus: () => true, // don't throw on redirects
maxRedirects: 0,
validateStatus: () => true, // accept 302
});
// Check if login succeeded — after redirects we should land on ePay
const finalUrl = response.request?.res?.responseUrl ?? response.config?.url ?? "";
const html = typeof response.data === "string" ? response.data : "";
console.log(
`[epay] Login response: status=${response.status}, ` +
`location=${response.headers?.location ?? "none"}`,
);
// Check for auth failure — OpenAM returns 200 with login form on failure
const html = typeof response.data === "string" ? response.data : "";
if (
finalUrl.includes("/openam/UI/Login") ||
html.includes("Authentication Failed") ||
html.includes("IDToken1")
response.status === 200 &&
(html.includes("Authentication Failed") ||
html.includes("Autentificare esuata") ||
(html.includes("IDToken1") && html.includes("IDToken2")))
) {
throw new Error("ePay login failed (invalid credentials)");
}
// Verify we have session cookies
const cookies = await this.jar.getCookies(BASE_URL);
const hasCookies =
cookies.some((c) => c.key === "JSESSIONID") ||
cookies.some((c) => c.key === "iPlanetDirectoryPro");
if (!hasCookies) {
// Check oassl domain too
const oasslCookies = await this.jar.getCookies(LOGIN_URL);
if (!oasslCookies.some((c) => c.key === "iPlanetDirectoryPro")) {
throw new Error("ePay login failed (no session cookie)");
// Step 2: Follow redirect to ePay to establish JSESSIONID
const location = response.headers?.location;
if (location) {
await this.client.get(location, {
timeout: DEFAULT_TIMEOUT_MS,
maxRedirects: 5,
validateStatus: () => true,
});
} else if (response.status === 200) {
// No redirect but 200 — try navigating to ePay directly
await this.client.get(`${BASE_URL}/LogIn.action`, {
timeout: DEFAULT_TIMEOUT_MS,
maxRedirects: 5,
validateStatus: () => true,
});
}
// Verify we have session cookies on any relevant domain
const epayDomain = "https://epay.ancpi.ro";
const oasslDomain = "https://oassl.ancpi.ro";
const allCookies = [
...(await this.jar.getCookies(epayDomain)),
...(await this.jar.getCookies(oasslDomain)),
...(await this.jar.getCookies(BASE_URL)),
];
const hasSession =
allCookies.some((c) => c.key === "iPlanetDirectoryPro") ||
allCookies.some((c) => c.key === "JSESSIONID");
if (!hasSession) {
console.error(
"[epay] No session cookie found. Cookies:",
allCookies.map((c) => `${c.key}=${c.value.slice(0, 10)}...`),
);
throw new Error("ePay login failed (no session cookie)");
}
console.log("[epay] Login successful.");