Files
quak/test/integration/live-login.ts
sneak e3e40229a5 Fix auth token encoding: use URL-safe base64 WITH padding
The Ente server validates the auth token as URL-safe base64 with
padding (matching Go's base64.URLEncoding). Our toBase64URL strips
padding, producing a 43-char token where the server expects 44. This
caused HTTP 401 'invalid token' on every authenticated call.

Adds toBase64URLPadded to the crypto module and uses it in unwrapAuth
for the token specifically. toBase64URL (no-padding) is kept for
general use (JWT-style contexts).

Adds test/integration/live-login.ts which logs into the dev account
(entedev2026jp@acidhou.se), unwraps keys, and fetches collections
from the real Ente API. Verified: 4 collections returned successfully.
2026-05-13 17:10:04 -07:00

65 lines
2.2 KiB
TypeScript

import { init } from "../../src/crypto/index.js";
import { ApiClient } from "../../src/api/client.js";
import { beginLogin } from "../../src/auth/login.js";
import { unwrapAuth } from "../../src/auth/unwrap.js";
// Dev account — not a secret, throwaway account for integration testing.
const EMAIL = "entedev2026jp@acidhou.se";
const PASSWORD = "loldongs";
const RECOVERY_KEY =
"deliver have behave collect void chicken boring embrace coast reflect squeeze cotton dish resemble license remain quick dwarf plastic ensure amused cry nasty equip";
void RECOVERY_KEY; // available if needed for account recovery tests
const main = async () => {
await init();
const api = new ApiClient();
console.log(`Logging in as ${EMAIL}...`);
const challenge = await beginLogin(api, EMAIL, PASSWORD);
console.log("beginLogin returned:", challenge.kind);
let response;
if (challenge.kind === "complete") {
response = challenge.response;
} else if (challenge.kind === "totp") {
console.error("Account requires TOTP — disable 2FA for dev testing");
process.exit(1);
} else if (challenge.kind === "emailOTP") {
console.error("Account uses email OTP — SRP not set up?");
process.exit(1);
} else {
console.error("Unexpected challenge:", challenge);
process.exit(1);
}
console.log("Got AuthorizationResponse, user ID:", response.id);
console.log("Unwrapping keys...");
const { masterKey, token } = await unwrapAuth(response, PASSWORD);
console.log("Master key length:", masterKey.length, "bytes");
console.log("Token length:", token.length, "chars");
api.setAuthToken(token);
console.log("\nFetching collections...");
const { collections } = await api.getJSON<{ collections: unknown[] }>(
"/collections/v2",
{ sinceTime: 0 },
);
console.log(`Got ${collections.length} collection(s)`);
for (const c of collections.slice(0, 5)) {
const col = c as Record<string, unknown>;
console.log(
` id=${col.id} type=${col.type} updationTime=${col.updationTime}`,
);
}
console.log("\nLive login test passed.");
};
main().catch((err) => {
console.error("FAILED:", err);
process.exit(1);
});