5 Commits

Author SHA1 Message Date
2c51074294 Red: mock server must serialize empty 2FA fields like Go does
The museum server's EmailAuthorizationResponse declares
passkeySessionID, accountsUrl, twoFactorSessionID, and
twoFactorSessionIDV2 without `omitempty`, so Go always sends them,
as "" when unset. The previous mock omitted the unset fields
entirely, which let the ?? -based dispatch pass in tests while the
real server's "" defeated it and dual-2FA logins fell through to
the unsupported passkey branch.
2026-06-10 11:25:25 -07:00
0024631ef3 Red: test TOTP preference when account has both passkey and TOTP
When an account has both passkeys and TOTP enrolled, the Ente server
returns passkeySessionID + twoFactorSessionIDV2 (deliberately not the
V1 twoFactorSessionID field, so old clients keep using passkeys).
quak only checked the V1 field, saw the passkey session, and threw
'Passkey authentication is not supported'. A CLI cannot do WebAuthn,
so it must take the TOTP path via the V2 session ID.
2026-06-10 11:04:49 -07:00
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
75b57cfb29 Phase 3b red: login flow tests with SRP mock server
Adds fast-srp-hap (the same SRP library Ente's web client uses, pinned
to 2.0.4) as a runtime dependency.

Tests build a full mock Ente server using fast-srp-hap's SrpServer to
exercise real SRP-6a math end-to-end. The mock handles:
  GET /users/srp/attributes
  POST /users/srp/create-session
  POST /users/srp/verify-session
  POST /users/two-factor/verify
  POST /users/ott
  POST /users/verify-email

7 tests covering:
  * SRP login completing successfully
  * SRP login requiring TOTP (returns { kind: 'totp' })
  * Wrong password (SRP M1 fails server-side checkM1)
  * Email MFA fallback (returns { kind: 'emailOTP' })
  * submitTOTP
  * requestEmailOTP + submitEmailOTP
2026-05-11 01:04:10 -07:00
6386a0ec9f Phase 3a red: auth.unwrapAuth tests and stub
Tests for the password-only decryption chain that follows a successful
login (SRP or email OTP, with or without 2FA). The unwrap covers:
  password -> KEK (Argon2id) -> masterKey (secretbox) ->
  secretKey (secretbox) -> tokenBytes (sealed box) -> base64url token

Each test builds a synthetic AuthorizationResponse using libsodium
directly and asserts unwrapAuth recovers the inputs byte for byte. The
test file also functions as the canonical description of the protocol.

Adds src/auth/types.ts with KeyAttributes, SRPAttributes,
AuthorizationResponse, and LoginChallenge declarations matching the
README's API reference. src/auth/unwrap.ts is the throwing stub; the
real implementation lands next.
2026-05-11 00:58:27 -07:00