Files
internxt-webdav/docs/auth-analysis.md
elpatron 262cffe4a6 Translate all user-facing output to English
- Scripts: start-webdav.cmd, stop-webdav.cmd (echo messages, REM comments)
- Server: server.js (console.log, HTTP error messages)
- Token tools: token-test.js, token-refresh.js
- Other: auth-poc.js, debug-name-decrypt.js, internxt-client.js, upload.js
- Docs: README, .env.example, docs/*.md

Made-with: Cursor
2026-02-28 16:37:28 +01:00

3.8 KiB
Raw Blame History

Internxt Auth Analysis: Web vs CLI vs Rclone

Core Finding: Client Identification Determines Access

The backend server blocks certain account tiers based on client identification:

Client clientName Login Method Endpoint Status for restricted tiers
drive-web drive-web login() /auth/login Allowed
drive-desktop drive-desktop login() /auth/login Allowed
internxt-cli internxt-cli loginAccess() /auth/login/access Blocked
rclone (rclone-adapter) loginAccess-like /auth/login/access Blocked

Sources

drive-web (auth.service.ts)

const getAuthClient = (authType: 'web' | 'desktop') => {
  const AUTH_CLIENT = {
    web: SdkFactory.getNewApiInstance().createAuthClient(),      // clientName: "drive-web"
    desktop: SdkFactory.getNewApiInstance().createDesktopAuthClient(),  // clientName: "drive-desktop"
  };
  return AUTH_CLIENT[authType];
};

// Login with authClient.login() - NOT loginAccess()
return authClient.login(loginDetails, cryptoProvider)
  • createAuthClient(): clientName: packageJson.name = "drive-web"
  • createDesktopAuthClient(): clientName: "drive-desktop"
  • Method: login() (not loginAccess)

CLI (auth.service.ts)

const authClient = SdkManager.instance.getAuth();
const data = await authClient.loginAccess(loginDetails, CryptoService.cryptoProvider);
  • getAppDetails(): clientName: packageJson.clientName = "internxt-cli" (from package.json)
  • Method: loginAccess() (not login)

SDK Factory (drive-web)

private static getAppDetails(): AppDetails {
  return {
    clientName: packageJson.name,   // "drive-web"
    clientVersion: packageJson.version,
    customHeaders,
  };
}

private static getDesktopAppDetails(): AppDetails {
  return {
    clientName: 'drive-desktop',
    clientVersion: packageJson.version,
  };
}

Solution for WebDAV Wrapper

Strategy: Configure the auth client to identify as drive-web and use login() instead of loginAccess().

  1. Use @internxt/sdk with Auth.client(apiUrl, appDetails, apiSecurity)
  2. Set appDetails: { clientName: "drive-web", clientVersion: "1.0" }
  3. Call login() (not loginAccess())
  4. Implement CryptoProvider like in drive-web (passToHash, decryptText, getKeys, parseAndDecryptUserKeys)

Dependencies for WebDAV Wrapper

  • @internxt/sdk (version 1.13.x or compatible drive-web uses 1.13.2)
  • @internxt/lib (for aes, Crypto)
  • Crypto logic from drive-web: app/crypto/services/keys.service, app/crypto/services/utils
  • Keys format: ECC + Kyber (post-quantum)

Current Status (as of analysis)

  • CRYPTO_SECRET: Correct (salt decryption OK with 6KYQBP847D4ATSFA)
  • loginWithoutKeys: Still returns "Wrong login credentials" backend may reject this flow for certain account types (e.g. mailbox.org partner)
  • login() with keys: Kyber-WASM fails under Windows (@dashlane/pqc-kem-kyber512-node)

Next Steps

  1. Test approach B: Browser-based token extraction log in via web, read session token from localStorage/DevTools, use in wrapper
  2. login() under Linux: Kyber package may work under Linux
  3. Internxt support: Ask whether partner accounts (mailbox.org) use different auth flows

CRYPTO_SECRET and API URL

From internxt/cli .env.template:

  • DRIVE_API_URL: https://gateway.internxt.com/drive
  • APP_CRYPTO_SECRET: 6KYQBP847D4ATSFA

The PoC uses these values as fallback.