#7671·server

API: /accounts/profile returns null KDF for Argon2id accounts authenticated via OAuth2 client_credentials (API key)

Author: noidgotenCreated May 19, 2026Updated May 20, 2026
Labelsbug

Steps To Reproduce

  1. On a Bitwarden Cloud account, set master-password KDF to Argon2id (Account Settings → Security → Master Password → Encryption Settings). Example: memory=64 MiB, iterations=4, parallelism=8.

  2. Obtain an OAuth2 access token via the API key flow:

    curl -X POST https://identity.bitwarden.com/connect/token
    -H "Bitwarden-Client-Name: cli"
    -H "Bitwarden-Client-Version: 2026.4.1"
    -H "Device-Type: 21"
    -H "Device-Identifier: $(uuidgen)"
    -H "Device-Name: curl-test"
    --data-urlencode grant_type=client_credentials
    --data-urlencode client_id="user."
    --data-urlencode client_secret=""
    --data-urlencode scope=api
    --data-urlencode deviceType=21
    --data-urlencode deviceIdentifier="$(uuidgen)"
    --data-urlencode deviceName=curl-test

  3. Call /accounts/profile with the returned access_token:

    curl https://api.bitwarden.com/accounts/profile
    -H "Authorization: Bearer "
    -H "Bitwarden-Client-Name: cli"
    -H "Bitwarden-Client-Version: 2026.4.1"
    -H "Device-Type: 21"
    -H "Device-Identifier: "
    -H "Device-Name: curl-test"

Expected Result

Response includes the account's actual KDF settings, e.g.:

{ "kdf": 1, "kdfIterations": 4, "kdfMemory": 64, "kdfParallelism": 8, "email": "[email protected]", ... }

(kdf: 1 = Argon2id per the KdfType enum)

Actual Result

{ "kdf": null, "kdfIterations": null, "kdfMemory": null, "kdfParallelism": null, "email": "[email protected]", ... }

All four KDF fields are null. Other profile fields (email, name, etc.) populate normally.

Screenshots or Videos

No response

Additional Context

Downstream impact (add to description or "additional context"): bw CLI 2026.3.0 and 2026.4.1 (bitwarden-cli-bin AUR + @bitwarden/cli on npm) cannot derive the master key after bw login --apikey. bw unlock --raw returns an 88-char session token, but every subsequent vault command (bw status, bw list items, etc.) sees kdfType: null in local state, treats the vault as locked, and falls back to the interactive master-password prompt — which also fails since KDF is unknown. Effectively makes the API-key auth path unusable on Argon2id accounts.

Same account works correctly on web vault, Desktop, and mobile clients; those use the password grant type which appears to return KDF normally.

Reproduces identically on Arch Linux and macOS, on two physically separate machines, with both pkg-bundled and npm-installed bw clients. Full local-state wipe (~/.config/Bitwarden CLI/) + API key rotation + re-login does not change the behavior — narrowing it to server-side, specific to the client_credentials grant + Argon2id account combination.

Build Version

Bitwarden Cloud (N/A)

Environment

Cloud (bitwarden.com)

Environment Details

  • Bitwarden Cloud: identity.bitwarden.com / api.bitwarden.com (US region)
  • Account KDF: Argon2id (memory=64 MiB, iterations=4, parallelism=8)
  • 2FA: WebAuthn (YubiKey) — note: API key login does authenticate successfully, so the token flow itself is fine; the regression is the profile response.
  • Affected clients:
    • bw CLI 2026.4.1 (bitwarden-cli-bin AUR, prebuilt pkg-bundled binary)
    • bw CLI 2026.3.0 (same source, prebuilt)
    • bw CLI 2026.4.1 (@bitwarden/cli npm, system Node.js)
  • Affected hosts: Arch Linux (kernel 7.0.9) and macOS
  • Date observed: 2026-05-18

Issue Tracking Info

  • I understand that work is tracked outside of Github. A PR will be linked to this issue should one be opened to address it, but Bitwarden doesn't use fields like "assigned", "milestone", or "project" to track progress.