bitwarden / bitwarden/server

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

Open
#7,671 8 comments 1 reaction 0 assignees View on GitHub
bug
Dominant language
C#
Stars
20.1k
Forks
1.8k
Avg merge
4d 8h
Merged PRs (30d)
75

Description

### 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": "user@example.com",
...
}

(kdf: 1 = Argon2id per the KdfType enum)

### Actual Result

{
"kdf": null,
"kdfIterations": null,
"kdfMemory": null,
"kdfParallelism": null,
"email": "user@example.com",
...
}

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

- [x] 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.

Contributor guide

Open the contributing guide

Research direction

Start by tracing the /accounts/profile endpoint and comparing its response for password-grant and client_credentials authentication with an Argon2id account. Reproduce the supplied API-key flow, then follow the profile mapping and existing API tests; done means all four KDF fields contain the account settings and the affected CLI can derive and use the master key.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api, authentication
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.