From 9e9b9059209c42169963a90ead01beb2845f69ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 19 Dec 2025 12:40:43 +0100 Subject: [PATCH] Add new accountKeys and masterPasswordUnlock fields --- src/api/core/mod.rs | 3 ++- src/api/identity.rs | 30 +++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs index 173a06b6..5d236bf5 100644 --- a/src/api/core/mod.rs +++ b/src/api/core/mod.rs @@ -217,7 +217,8 @@ fn config() -> Json { // We should make sure that we keep this updated when we support the new server features // Version history: // - Individual cipher key encryption: 2024.2.0 - "version": "2025.6.0", + // - Mobile app support for MasterPasswordUnlockData: 2025.8.0 + "version": "2025.12.0", "gitHash": option_env!("GIT_REV"), "server": { "name": "Vaultwarden", diff --git a/src/api/identity.rs b/src/api/identity.rs index 52e2c659..4992c1e7 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -463,6 +463,32 @@ async fn authenticated_response( let master_password_policy = master_password_policy(user, conn).await; + + let has_master_password = !user.password_hash.is_empty(); + let master_password_unlock = if has_master_password { + json!({ + "Kdf": { + "KdfType": user.client_kdf_type, + "Iterations": user.client_kdf_iter, + "Memory": user.client_kdf_memory, + "Parallelism": user.client_kdf_parallelism + }, + "MasterKeyEncryptedUserKey": user.akey, + "Salt": user.email + }) + } else { + Value::Null + }; + + let account_keys = json!({ + "publicKeyEncryptionKeyPair": { + "wrappedPrivateKey": user.private_key, + "publicKey": user.public_key, + "Object": "publicKeyEncryptionKeyPair" + }, + "Object": "privateKeys" + }); + let mut result = json!({ "access_token": auth_tokens.access_token(), "expires_in": auth_tokens.expires_in(), @@ -477,8 +503,10 @@ async fn authenticated_response( "ForcePasswordReset": false, "MasterPasswordPolicy": master_password_policy, "scope": auth_tokens.scope(), + "AccountKeys": account_keys, "UserDecryptionOptions": { - "HasMasterPassword": !user.password_hash.is_empty(), + "HasMasterPassword": has_master_password, + "MasterPasswordUnlock": master_password_unlock, "Object": "userDecryptionOptions" }, });