fix(ancpi): GET login page before POST to establish form tokens
OpenAM requires an initial GET to set session cookies before the credentials POST. Without it, POST returns 500 and only sets AMAuthCookie (intermediate) instead of iPlanetDirectoryPro (final SSO). Then navigate to ePay goto URL to establish JSESSIONID. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -128,11 +128,19 @@ export class EpayClient {
|
||||
|
||||
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 gotoUrl = "http://epay.ancpi.ro:80/epay/LogIn.action";
|
||||
const loginUrlFull = `${LOGIN_URL}?module=SelfRegistration&goto=${encodeURIComponent(gotoUrl)}`;
|
||||
|
||||
// Step 1: GET the login page first (sets initial cookies + form tokens)
|
||||
await this.client.get(loginUrlFull, {
|
||||
timeout: DEFAULT_TIMEOUT_MS,
|
||||
maxRedirects: 5,
|
||||
validateStatus: () => true,
|
||||
});
|
||||
|
||||
// Step 2: POST credentials
|
||||
const body = `IDToken1=${encodeURIComponent(this.username)}&IDToken2=${encodeURIComponent(this.password)}`;
|
||||
|
||||
// POST login — follow all redirects, let cookie jar capture everything
|
||||
const response = await this.client.post(loginUrlFull, body, {
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
@@ -146,112 +154,66 @@ export class EpayClient {
|
||||
const finalUrl =
|
||||
response.request?.res?.responseUrl ??
|
||||
response.request?.responseURL ??
|
||||
response.config?.url ??
|
||||
"";
|
||||
const html = typeof response.data === "string" ? response.data : "";
|
||||
|
||||
console.log(
|
||||
`[epay] Login: status=${response.status}, finalUrl=${finalUrl.slice(0, 100)}`,
|
||||
`[epay] Login POST: status=${response.status}, finalUrl=${finalUrl.slice(0, 120)}`,
|
||||
);
|
||||
|
||||
// Auth failure: OpenAM returns login form again
|
||||
// Auth failure check
|
||||
if (
|
||||
html.includes("Authentication Failed") ||
|
||||
html.includes("Autentificare esuata") ||
|
||||
(finalUrl.includes("/openam/UI/Login") &&
|
||||
html.includes("IDToken1") &&
|
||||
html.includes("IDToken2"))
|
||||
html.includes("Autentificare esuata")
|
||||
) {
|
||||
throw new Error("ePay login failed (invalid credentials)");
|
||||
}
|
||||
|
||||
// After redirect chain, navigate to ePay explicitly to ensure JSESSIONID
|
||||
if (!finalUrl.includes("epay.ancpi.ro")) {
|
||||
await this.client.get(`${BASE_URL}/LogIn.action`, {
|
||||
timeout: DEFAULT_TIMEOUT_MS,
|
||||
maxRedirects: 5,
|
||||
validateStatus: () => true,
|
||||
});
|
||||
}
|
||||
// Step 3: Navigate to ePay to establish JSESSIONID
|
||||
// Try the goto URL (HTTP) and HTTPS variants
|
||||
const epayUrls = [gotoUrl, `${BASE_URL}/LogIn.action`];
|
||||
let loggedIn = false;
|
||||
|
||||
// Log all cookies for debugging
|
||||
const domains = [
|
||||
"https://epay.ancpi.ro",
|
||||
"https://oassl.ancpi.ro",
|
||||
"http://epay.ancpi.ro",
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[epay] Cookies after login (${allCookies.length}):`,
|
||||
JSON.stringify(allCookies),
|
||||
);
|
||||
|
||||
// OpenAM at ANCPI uses AMAuthCookie (not iPlanetDirectoryPro)
|
||||
const SESSION_COOKIE_NAMES = [
|
||||
"AMAuthCookie",
|
||||
"iPlanetDirectoryPro",
|
||||
"JSESSIONID",
|
||||
];
|
||||
const hasSession = allCookies.some((c) =>
|
||||
SESSION_COOKIE_NAMES.includes(c.key),
|
||||
);
|
||||
|
||||
if (!hasSession) {
|
||||
throw new Error("ePay login failed (no session cookie)");
|
||||
}
|
||||
|
||||
// Navigate to ePay to establish JSESSIONID
|
||||
// CRITICAL: ePay's goto URL is HTTP (http://epay.ancpi.ro:80), not HTTPS.
|
||||
// The AMAuthCookie must be sent to this exact URL for ePay to create a session.
|
||||
const epayUrls = [
|
||||
"http://epay.ancpi.ro:80/epay/LogIn.action",
|
||||
"http://epay.ancpi.ro/epay/LogIn.action",
|
||||
`${BASE_URL}/LogIn.action`,
|
||||
];
|
||||
|
||||
let jsessionEstablished = false;
|
||||
for (const epayUrl of epayUrls) {
|
||||
try {
|
||||
const epayResponse = await this.client.get(epayUrl, {
|
||||
timeout: DEFAULT_TIMEOUT_MS,
|
||||
maxRedirects: 5,
|
||||
maxRedirects: 10,
|
||||
validateStatus: () => true,
|
||||
});
|
||||
const epayHtml = String(epayResponse.data ?? "");
|
||||
|
||||
// Check if we got the logged-in page (has credit info or user menu)
|
||||
if (
|
||||
epayHtml.includes("credit") ||
|
||||
epayHtml.includes("puncte de credit") ||
|
||||
epayHtml.includes("LogOut") ||
|
||||
epayHtml.includes("Istoric")
|
||||
epayHtml.includes("Istoric Comenzi")
|
||||
) {
|
||||
jsessionEstablished = true;
|
||||
loggedIn = true;
|
||||
console.log(`[epay] Session established via ${epayUrl}`);
|
||||
break;
|
||||
}
|
||||
} catch {
|
||||
// Try next URL
|
||||
// Try next
|
||||
}
|
||||
}
|
||||
|
||||
if (!jsessionEstablished) {
|
||||
console.warn("[epay] Could not establish ePay session, but AMAuthCookie is set.");
|
||||
if (!loggedIn) {
|
||||
// Log cookies for debugging
|
||||
const cookieKeys: string[] = [];
|
||||
for (const domain of [
|
||||
"https://epay.ancpi.ro",
|
||||
"https://oassl.ancpi.ro",
|
||||
"http://epay.ancpi.ro",
|
||||
]) {
|
||||
try {
|
||||
const cookies = await this.jar.getCookies(domain);
|
||||
for (const c of cookies) cookieKeys.push(`${c.key}@${domain}`);
|
||||
} catch {
|
||||
/* skip */
|
||||
}
|
||||
}
|
||||
console.error(`[epay] Login failed. Cookies: ${cookieKeys.join(", ")}`);
|
||||
throw new Error("ePay login failed (could not establish session)");
|
||||
}
|
||||
|
||||
console.log("[epay] Login successful.");
|
||||
|
||||
Reference in New Issue
Block a user