fix(ancpi): follow full redirect chain for OpenAM login, add cookie debug

Let axios follow all redirects (maxRedirects=10) so cookie jar captures
iPlanetDirectoryPro from the chain. Explicitly navigate to ePay after
login to ensure JSESSIONID. Log all cookies for debugging. Last resort:
verify login by checking if credit info is visible on ePay page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-23 00:32:30 +02:00
parent 259f56396b
commit b9993f0573
+61 -33
View File
@@ -132,43 +132,41 @@ export class EpayClient {
const body = `IDToken1=${encodeURIComponent(this.username)}&IDToken2=${encodeURIComponent(this.password)}`; const body = `IDToken1=${encodeURIComponent(this.username)}&IDToken2=${encodeURIComponent(this.password)}`;
// Step 1: POST login — don't follow redirects so we capture cookies // POST login — follow all redirects, let cookie jar capture everything
const response = await this.client.post(loginUrlFull, body, { const response = await this.client.post(loginUrlFull, body, {
headers: { headers: {
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
Referer: loginUrlFull, Referer: loginUrlFull,
}, },
timeout: DEFAULT_TIMEOUT_MS, timeout: DEFAULT_TIMEOUT_MS,
maxRedirects: 0, maxRedirects: 10,
validateStatus: () => true, // accept 302 validateStatus: () => true,
}); });
const finalUrl =
response.request?.res?.responseUrl ??
response.request?.responseURL ??
response.config?.url ??
"";
const html = typeof response.data === "string" ? response.data : "";
console.log( console.log(
`[epay] Login response: status=${response.status}, ` + `[epay] Login: status=${response.status}, finalUrl=${finalUrl.slice(0, 100)}`,
`location=${response.headers?.location ?? "none"}`,
); );
// Check for auth failure OpenAM returns 200 with login form on failure // Auth failure: OpenAM returns login form again
const html = typeof response.data === "string" ? response.data : "";
if ( if (
response.status === 200 && html.includes("Authentication Failed") ||
(html.includes("Authentication Failed") ||
html.includes("Autentificare esuata") || html.includes("Autentificare esuata") ||
(html.includes("IDToken1") && html.includes("IDToken2"))) (finalUrl.includes("/openam/UI/Login") &&
html.includes("IDToken1") &&
html.includes("IDToken2"))
) { ) {
throw new Error("ePay login failed (invalid credentials)"); throw new Error("ePay login failed (invalid credentials)");
} }
// Step 2: Follow redirect to ePay to establish JSESSIONID // After redirect chain, navigate to ePay explicitly to ensure JSESSIONID
const location = response.headers?.location; if (!finalUrl.includes("epay.ancpi.ro")) {
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`, { await this.client.get(`${BASE_URL}/LogIn.action`, {
timeout: DEFAULT_TIMEOUT_MS, timeout: DEFAULT_TIMEOUT_MS,
maxRedirects: 5, maxRedirects: 5,
@@ -176,24 +174,54 @@ export class EpayClient {
}); });
} }
// Verify we have session cookies on any relevant domain // Log all cookies for debugging
const epayDomain = "https://epay.ancpi.ro"; const domains = [
const oasslDomain = "https://oassl.ancpi.ro"; "https://epay.ancpi.ro",
const allCookies = [ "https://oassl.ancpi.ro",
...(await this.jar.getCookies(epayDomain)), "http://epay.ancpi.ro",
...(await this.jar.getCookies(oasslDomain)), BASE_URL,
...(await this.jar.getCookies(BASE_URL)),
]; ];
const allCookies: Array<{ domain: string; key: string; value: string }> = [];
for (const domain of domains) {
try {
const cookies = await this.jar.getCookies(domain);
for (const c of cookies) {
allCookies.push({
domain,
key: c.key,
value: c.value.slice(0, 15) + "...",
});
}
} catch {
// domain not applicable
}
}
const hasSession = console.log(
allCookies.some((c) => c.key === "iPlanetDirectoryPro") || `[epay] Cookies after login (${allCookies.length}):`,
allCookies.some((c) => c.key === "JSESSIONID"); JSON.stringify(allCookies),
);
const hasSession = allCookies.some(
(c) => c.key === "iPlanetDirectoryPro" || c.key === "JSESSIONID",
);
if (!hasSession) { if (!hasSession) {
console.error( // Last resort: try the full HTML for credit info — if we can see credits, we're logged in
"[epay] No session cookie found. Cookies:", const checkResponse = await this.client.get(
allCookies.map((c) => `${c.key}=${c.value.slice(0, 10)}...`), `${BASE_URL}/LogIn.action`,
{
timeout: DEFAULT_TIMEOUT_MS,
maxRedirects: 5,
validateStatus: () => true,
},
); );
const checkHtml = String(checkResponse.data ?? "");
if (checkHtml.includes("puncte de credit")) {
console.log("[epay] Login successful (verified via credit check).");
return;
}
throw new Error("ePay login failed (no session cookie)"); throw new Error("ePay login failed (no session cookie)");
} }