mirror of
https://github.com/bitwarden/mobile
synced 2025-12-21 02:33:36 +00:00
[PM-3462] Handle force password reset on mobile with TDE (#2694)
* [PM-3462] Handle force password reset on mobile with TDE * [PM-3462] update references to refactored crypto method - fix kc bug, we were sending private key instead of user key to server - rename kc service method to be correct * [PM-3462] Update TwoFactorPage login logic * [PM-3462] Added pending admin request check to TwoFactorPage * [PM-3462] Added new exception types for null keys --------- Co-authored-by: André Bispo <abispo@bitwarden.com>
This commit is contained in:
@@ -211,33 +211,41 @@ namespace Bit.App.Pages
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trusted device option is sent regardless if this is a trusted device or not
|
||||||
|
// If it is trusted, it will have the necessary keys
|
||||||
if (decryptOptions?.TrustedDeviceOption != null)
|
if (decryptOptions?.TrustedDeviceOption != null)
|
||||||
{
|
{
|
||||||
var pendingRequest = await _stateService.GetPendingAdminAuthRequestAsync();
|
if (await _deviceTrustCryptoService.IsDeviceTrustedAsync())
|
||||||
// If user doesn't have a MP, but has reset password permission, they must set a MP
|
|
||||||
if (!decryptOptions.HasMasterPassword &&
|
|
||||||
decryptOptions.TrustedDeviceOption.HasManageResetPasswordPermission)
|
|
||||||
{
|
|
||||||
StartSetPasswordAction?.Invoke();
|
|
||||||
}
|
|
||||||
else if (response.ForcePasswordReset)
|
|
||||||
{
|
|
||||||
UpdateTempPasswordAction?.Invoke();
|
|
||||||
}
|
|
||||||
else if (await _deviceTrustCryptoService.IsDeviceTrustedAsync())
|
|
||||||
{
|
{
|
||||||
|
// If we have a device key but no keys on server, we need to remove the device key
|
||||||
if (decryptOptions.TrustedDeviceOption.EncryptedPrivateKey == null && decryptOptions.TrustedDeviceOption.EncryptedUserKey == null)
|
if (decryptOptions.TrustedDeviceOption.EncryptedPrivateKey == null && decryptOptions.TrustedDeviceOption.EncryptedUserKey == null)
|
||||||
{
|
{
|
||||||
await _deviceTrustCryptoService.RemoveTrustedDeviceAsync();
|
await _deviceTrustCryptoService.RemoveTrustedDeviceAsync();
|
||||||
StartDeviceApprovalOptionsAction?.Invoke();
|
StartDeviceApprovalOptionsAction?.Invoke();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
// If user doesn't have a MP, but has reset password permission, they must set a MP
|
||||||
|
if (!decryptOptions.HasMasterPassword &&
|
||||||
|
decryptOptions.TrustedDeviceOption.HasManageResetPasswordPermission)
|
||||||
{
|
{
|
||||||
_syncService.FullSyncAsync(true).FireAndForget();
|
StartSetPasswordAction?.Invoke();
|
||||||
SsoAuthSuccessAction?.Invoke();
|
return;
|
||||||
}
|
}
|
||||||
|
// Update temp password only if the device is trusted and therefore has a decrypted User Key set
|
||||||
|
if (response.ForcePasswordReset)
|
||||||
|
{
|
||||||
|
UpdateTempPasswordAction?.Invoke();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Device is trusted and has keys, so we can decrypt
|
||||||
|
_syncService.FullSyncAsync(true).FireAndForget();
|
||||||
|
SsoAuthSuccessAction?.Invoke();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (pendingRequest != null)
|
|
||||||
|
// Check for pending Admin Auth requests before navigating to device approval options
|
||||||
|
var pendingRequest = await _stateService.GetPendingAdminAuthRequestAsync();
|
||||||
|
if (pendingRequest != null)
|
||||||
{
|
{
|
||||||
var authRequest = await _authService.GetPasswordlessLoginRequestByIdAsync(pendingRequest.Id);
|
var authRequest = await _authService.GetPasswordlessLoginRequestByIdAsync(pendingRequest.Id);
|
||||||
if (authRequest?.RequestApproved == true)
|
if (authRequest?.RequestApproved == true)
|
||||||
@@ -268,18 +276,14 @@ namespace Bit.App.Pages
|
|||||||
// In the standard, non TDE case, a user must set password if they don't
|
// In the standard, non TDE case, a user must set password if they don't
|
||||||
// have one and they aren't using key connector.
|
// have one and they aren't using key connector.
|
||||||
// Note: TDE & Key connector are mutually exclusive org config options.
|
// Note: TDE & Key connector are mutually exclusive org config options.
|
||||||
if (response.ResetMasterPassword || (decryptOptions?.RequireSetPassword ?? false))
|
if (response.ResetMasterPassword || (decryptOptions?.RequireSetPassword == true))
|
||||||
{
|
{
|
||||||
|
// TODO: We need to look into how to handle this when Org removes TDE
|
||||||
|
// Will we have the User Key by now to set a new password?
|
||||||
StartSetPasswordAction?.Invoke();
|
StartSetPasswordAction?.Invoke();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.ForcePasswordReset)
|
|
||||||
{
|
|
||||||
UpdateTempPasswordAction?.Invoke();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_syncService.FullSyncAsync(true).FireAndForget();
|
_syncService.FullSyncAsync(true).FireAndForget();
|
||||||
SsoAuthSuccessAction?.Invoke();
|
SsoAuthSuccessAction?.Invoke();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,7 +178,10 @@ namespace Bit.App.Pages
|
|||||||
Email = Email.Trim().ToLower();
|
Email = Email.Trim().ToLower();
|
||||||
var kdfConfig = new KdfConfig(KdfType.PBKDF2_SHA256, Constants.Pbkdf2Iterations, null, null);
|
var kdfConfig = new KdfConfig(KdfType.PBKDF2_SHA256, Constants.Pbkdf2Iterations, null, null);
|
||||||
var newMasterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, Email, kdfConfig);
|
var newMasterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, Email, kdfConfig);
|
||||||
var (newUserKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync(newMasterKey);
|
var (newUserKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync(
|
||||||
|
newMasterKey,
|
||||||
|
await _cryptoService.MakeUserKeyAsync()
|
||||||
|
);
|
||||||
var hashedPassword = await _cryptoService.HashMasterKeyAsync(MasterPassword, newMasterKey);
|
var hashedPassword = await _cryptoService.HashMasterKeyAsync(MasterPassword, newMasterKey);
|
||||||
var (newPublicKey, newProtectedPrivateKey) = await _cryptoService.MakeKeyPairAsync(newUserKey);
|
var (newPublicKey, newProtectedPrivateKey) = await _cryptoService.MakeKeyPairAsync(newUserKey);
|
||||||
var request = new RegisterRequest
|
var request = new RegisterRequest
|
||||||
|
|||||||
@@ -169,7 +169,8 @@ namespace Bit.App.Pages
|
|||||||
var masterPasswordHash = await _cryptoService.HashMasterKeyAsync(MasterPassword, newMasterKey, HashPurpose.ServerAuthorization);
|
var masterPasswordHash = await _cryptoService.HashMasterKeyAsync(MasterPassword, newMasterKey, HashPurpose.ServerAuthorization);
|
||||||
var localMasterPasswordHash = await _cryptoService.HashMasterKeyAsync(MasterPassword, newMasterKey, HashPurpose.LocalAuthorization);
|
var localMasterPasswordHash = await _cryptoService.HashMasterKeyAsync(MasterPassword, newMasterKey, HashPurpose.LocalAuthorization);
|
||||||
|
|
||||||
var (newUserKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync(newMasterKey);
|
var (newUserKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync(newMasterKey,
|
||||||
|
await _cryptoService.GetUserKeyAsync() ?? await _cryptoService.MakeUserKeyAsync());
|
||||||
|
|
||||||
var (newPublicKey, newProtectedPrivateKey) = await _cryptoService.MakeKeyPairAsync(newUserKey);
|
var (newPublicKey, newProtectedPrivateKey) = await _cryptoService.MakeKeyPairAsync(newUserKey);
|
||||||
var request = new SetPasswordRequest
|
var request = new SetPasswordRequest
|
||||||
|
|||||||
@@ -326,27 +326,56 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
if (decryptOptions?.TrustedDeviceOption != null)
|
if (decryptOptions?.TrustedDeviceOption != null)
|
||||||
{
|
{
|
||||||
// If user doesn't have a MP, but has reset password permission, they must set a MP
|
if (await _deviceTrustCryptoService.IsDeviceTrustedAsync())
|
||||||
if (!decryptOptions.HasMasterPassword &&
|
|
||||||
decryptOptions.TrustedDeviceOption.HasManageResetPasswordPermission)
|
|
||||||
{
|
|
||||||
StartSetPasswordAction?.Invoke();
|
|
||||||
}
|
|
||||||
else if (result.ForcePasswordReset)
|
|
||||||
{
|
|
||||||
UpdateTempPasswordAction?.Invoke();
|
|
||||||
}
|
|
||||||
else if (await _deviceTrustCryptoService.IsDeviceTrustedAsync())
|
|
||||||
{
|
{
|
||||||
|
// If we have a device key but no keys on server, we need to remove the device key
|
||||||
if (decryptOptions.TrustedDeviceOption.EncryptedPrivateKey == null && decryptOptions.TrustedDeviceOption.EncryptedUserKey == null)
|
if (decryptOptions.TrustedDeviceOption.EncryptedPrivateKey == null && decryptOptions.TrustedDeviceOption.EncryptedUserKey == null)
|
||||||
{
|
{
|
||||||
await _deviceTrustCryptoService.RemoveTrustedDeviceAsync();
|
await _deviceTrustCryptoService.RemoveTrustedDeviceAsync();
|
||||||
StartDeviceApprovalOptionsAction?.Invoke();
|
StartDeviceApprovalOptionsAction?.Invoke();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If user doesn't have a MP, but has reset password permission, they must set a MP
|
||||||
|
if (!decryptOptions.HasMasterPassword &&
|
||||||
|
decryptOptions.TrustedDeviceOption.HasManageResetPasswordPermission)
|
||||||
|
{
|
||||||
|
StartSetPasswordAction?.Invoke();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Update temp password only if the device is trusted and therefore has a decrypted User Key set
|
||||||
|
if (result.ForcePasswordReset)
|
||||||
|
{
|
||||||
|
UpdateTempPasswordAction?.Invoke();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Device is trusted and has keys, so we can decrypt
|
||||||
|
_syncService.FullSyncAsync(true).FireAndForget();
|
||||||
|
await TwoFactorAuthSuccessAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for pending Admin Auth requests before navigating to device approval options
|
||||||
|
var pendingRequest = await _stateService.GetPendingAdminAuthRequestAsync();
|
||||||
|
if (pendingRequest != null)
|
||||||
|
{
|
||||||
|
var authRequest = await _authService.GetPasswordlessLoginRequestByIdAsync(pendingRequest.Id);
|
||||||
|
if (authRequest?.RequestApproved == true)
|
||||||
|
{
|
||||||
|
var authResult = await _authService.LogInPasswordlessAsync(true, await _stateService.GetActiveUserEmailAsync(), authRequest.RequestAccessCode, pendingRequest.Id, pendingRequest.PrivateKey, authRequest.Key, authRequest.MasterPasswordHash);
|
||||||
|
if (authResult == null && await _stateService.IsAuthenticatedAsync())
|
||||||
|
{
|
||||||
|
await Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(
|
||||||
|
() => _platformUtilsService.ShowToast("info", null, AppResources.LoginApproved));
|
||||||
|
await _stateService.SetPendingAdminAuthRequestAsync(null);
|
||||||
|
_syncService.FullSyncAsync(true).FireAndForget();
|
||||||
|
await TwoFactorAuthSuccessAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_syncService.FullSyncAsync(true).FireAndForget();
|
await _stateService.SetPendingAdminAuthRequestAsync(null);
|
||||||
await TwoFactorAuthSuccessAsync();
|
StartDeviceApprovalOptionsAction?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -361,16 +390,12 @@ namespace Bit.App.Pages
|
|||||||
// Note: TDE & Key connector are mutually exclusive org config options.
|
// Note: TDE & Key connector are mutually exclusive org config options.
|
||||||
if (result.ResetMasterPassword || (decryptOptions?.RequireSetPassword ?? false))
|
if (result.ResetMasterPassword || (decryptOptions?.RequireSetPassword ?? false))
|
||||||
{
|
{
|
||||||
|
// TODO: We need to look into how to handle this when Org removes TDE
|
||||||
|
// Will we have the User Key by now to set a new password?
|
||||||
StartSetPasswordAction?.Invoke();
|
StartSetPasswordAction?.Invoke();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.ForcePasswordReset)
|
|
||||||
{
|
|
||||||
UpdateTempPasswordAction?.Invoke();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_syncService.FullSyncAsync(true).FireAndForget();
|
_syncService.FullSyncAsync(true).FireAndForget();
|
||||||
await TwoFactorAuthSuccessAsync();
|
await TwoFactorAuthSuccessAsync();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace Bit.Core.Abstractions
|
|||||||
Task PutOrganizationUserResetPasswordEnrollmentAsync(string orgId, string userId,
|
Task PutOrganizationUserResetPasswordEnrollmentAsync(string orgId, string userId,
|
||||||
OrganizationUserResetPasswordEnrollmentRequest request);
|
OrganizationUserResetPasswordEnrollmentRequest request);
|
||||||
Task<KeyConnectorUserKeyResponse> GetMasterKeyFromKeyConnectorAsync(string keyConnectorUrl);
|
Task<KeyConnectorUserKeyResponse> GetMasterKeyFromKeyConnectorAsync(string keyConnectorUrl);
|
||||||
Task PostUserKeyToKeyConnector(string keyConnectorUrl, KeyConnectorUserKeyRequest request);
|
Task PostMasterKeyToKeyConnector(string keyConnectorUrl, KeyConnectorUserKeyRequest request);
|
||||||
Task PostSetKeyConnectorKey(SetKeyConnectorKeyRequest request);
|
Task PostSetKeyConnectorKey(SetKeyConnectorKeyRequest request);
|
||||||
Task PostConvertToKeyConnector();
|
Task PostConvertToKeyConnector();
|
||||||
Task PostLeaveOrganization(string id);
|
Task PostLeaveOrganization(string id);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Bit.Core.Abstractions
|
|||||||
Task<MasterKey> GetMasterKeyAsync(string userId = null);
|
Task<MasterKey> GetMasterKeyAsync(string userId = null);
|
||||||
Task<MasterKey> MakeMasterKeyAsync(string password, string email, KdfConfig kdfConfig);
|
Task<MasterKey> MakeMasterKeyAsync(string password, string email, KdfConfig kdfConfig);
|
||||||
Task ClearMasterKeyAsync(string userId = null);
|
Task ClearMasterKeyAsync(string userId = null);
|
||||||
Task<Tuple<UserKey, EncString>> EncryptUserKeyWithMasterKeyAsync(MasterKey masterKey);
|
Task<Tuple<UserKey, EncString>> EncryptUserKeyWithMasterKeyAsync(MasterKey masterKey, UserKey userKey = null);
|
||||||
Task<UserKey> DecryptUserKeyWithMasterKeyAsync(MasterKey masterKey, EncString encUserKey = null, string userId = null);
|
Task<UserKey> DecryptUserKeyWithMasterKeyAsync(MasterKey masterKey, EncString encUserKey = null, string userId = null);
|
||||||
Task<Tuple<SymmetricCryptoKey, EncString>> MakeDataEncKeyAsync(SymmetricCryptoKey key);
|
Task<Tuple<SymmetricCryptoKey, EncString>> MakeDataEncKeyAsync(SymmetricCryptoKey key);
|
||||||
Task<string> HashMasterKeyAsync(string password, MasterKey key, HashPurpose hashPurpose = HashPurpose.ServerAuthorization);
|
Task<string> HashMasterKeyAsync(string password, MasterKey key, HashPurpose hashPurpose = HashPurpose.ServerAuthorization);
|
||||||
|
|||||||
12
src/Core/Exceptions/MasterKeyNullException.cs
Normal file
12
src/Core/Exceptions/MasterKeyNullException.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
namespace Bit.Core.Exceptions
|
||||||
|
{
|
||||||
|
public class MasterKeyNullException : Exception
|
||||||
|
{
|
||||||
|
public MasterKeyNullException()
|
||||||
|
: base("MasterKey is null.")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
12
src/Core/Exceptions/UserKeyNullException.cs
Normal file
12
src/Core/Exceptions/UserKeyNullException.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
namespace Bit.Core.Exceptions
|
||||||
|
{
|
||||||
|
public class UserKeyNullException : Exception
|
||||||
|
{
|
||||||
|
public UserKeyNullException()
|
||||||
|
: base("UserKey is null.")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
|
||||||
namespace Bit.Core.Models.Domain
|
namespace Bit.Core.Models.Domain
|
||||||
@@ -8,6 +9,8 @@ namespace Bit.Core.Models.Domain
|
|||||||
public bool TwoFactor { get; set; }
|
public bool TwoFactor { get; set; }
|
||||||
public bool CaptchaNeeded => !string.IsNullOrWhiteSpace(CaptchaSiteKey);
|
public bool CaptchaNeeded => !string.IsNullOrWhiteSpace(CaptchaSiteKey);
|
||||||
public string CaptchaSiteKey { get; set; }
|
public string CaptchaSiteKey { get; set; }
|
||||||
|
// TODO: PM-3287 - Remove after 3 releases of backwards compatibility - Target release 2023.12
|
||||||
|
[Obsolete("Use AccountDecryptionOptions to determine if the user does not have a MP")]
|
||||||
public bool ResetMasterPassword { get; set; }
|
public bool ResetMasterPassword { get; set; }
|
||||||
public bool ForcePasswordReset { get; set; }
|
public bool ForcePasswordReset { get; set; }
|
||||||
public Dictionary<TwoFactorProviderType, Dictionary<string, object>> TwoFactorProviders { get; set; }
|
public Dictionary<TwoFactorProviderType, Dictionary<string, object>> TwoFactorProviders { get; set; }
|
||||||
|
|||||||
@@ -541,7 +541,7 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task PostUserKeyToKeyConnector(string keyConnectorUrl, KeyConnectorUserKeyRequest request)
|
public async Task PostMasterKeyToKeyConnector(string keyConnectorUrl, KeyConnectorUserKeyRequest request)
|
||||||
{
|
{
|
||||||
using (var requestMessage = new HttpRequestMessage())
|
using (var requestMessage = new HttpRequestMessage())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -240,7 +240,13 @@ namespace Bit.Core.Services
|
|||||||
public async Task<AuthResult> LogInSsoAsync(string code, string codeVerifier, string redirectUrl, string orgId)
|
public async Task<AuthResult> LogInSsoAsync(string code, string codeVerifier, string redirectUrl, string orgId)
|
||||||
{
|
{
|
||||||
SelectedTwoFactorProviderType = null;
|
SelectedTwoFactorProviderType = null;
|
||||||
return await LogInHelperAsync(null, null, null, code, codeVerifier, redirectUrl, null, orgId: orgId);
|
var result = await LogInHelperAsync(null, null, null, code, codeVerifier, redirectUrl, null, orgId: orgId);
|
||||||
|
if (result.ForcePasswordReset)
|
||||||
|
{
|
||||||
|
await _stateService.SetForcePasswordResetReasonAsync(ForcePasswordResetReason.AdminForcePasswordReset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AuthResult> LogInTwoFactorAsync(TwoFactorProviderType twoFactorProvider, string twoFactorToken,
|
public async Task<AuthResult> LogInTwoFactorAsync(TwoFactorProviderType twoFactorProvider, string twoFactorToken,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Models.Domain;
|
using Bit.Core.Models.Domain;
|
||||||
using Bit.Core.Models.Response;
|
using Bit.Core.Models.Response;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
@@ -152,9 +153,13 @@ namespace Bit.Core.Services
|
|||||||
return _stateService.SetMasterKeyAsync(null, userId);
|
return _stateService.SetMasterKeyAsync(null, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Tuple<UserKey, EncString>> EncryptUserKeyWithMasterKeyAsync(MasterKey masterKey)
|
public async Task<Tuple<UserKey, EncString>> EncryptUserKeyWithMasterKeyAsync(MasterKey masterKey, UserKey userKey = null)
|
||||||
{
|
{
|
||||||
var userKey = await GetUserKeyAsync() ?? await MakeUserKeyAsync();
|
userKey ??= await GetUserKeyAsync();
|
||||||
|
if (userKey == null)
|
||||||
|
{
|
||||||
|
throw new UserKeyNullException();
|
||||||
|
}
|
||||||
return await BuildProtectedSymmetricKeyAsync(masterKey, userKey.Key, keyBytes => new UserKey(keyBytes));
|
return await BuildProtectedSymmetricKeyAsync(masterKey, userKey.Key, keyBytes => new UserKey(keyBytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +168,7 @@ namespace Bit.Core.Services
|
|||||||
masterKey ??= await GetMasterKeyAsync(userId);
|
masterKey ??= await GetMasterKeyAsync(userId);
|
||||||
if (masterKey == null)
|
if (masterKey == null)
|
||||||
{
|
{
|
||||||
throw new Exception("No master key found.");
|
throw new MasterKeyNullException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encUserKey == null)
|
if (encUserKey == null)
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ namespace Bit.Core.Services
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var keyConnectorRequest = new KeyConnectorUserKeyRequest(masterKey.EncKeyB64);
|
var keyConnectorRequest = new KeyConnectorUserKeyRequest(masterKey.EncKeyB64);
|
||||||
await _apiService.PostUserKeyToKeyConnector(organization.KeyConnectorUrl, keyConnectorRequest);
|
await _apiService.PostMasterKeyToKeyConnector(organization.KeyConnectorUrl, keyConnectorRequest);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -95,13 +95,15 @@ namespace Bit.Core.Services
|
|||||||
var keyConnectorRequest = new KeyConnectorUserKeyRequest(newMasterKey.EncKeyB64);
|
var keyConnectorRequest = new KeyConnectorUserKeyRequest(newMasterKey.EncKeyB64);
|
||||||
await _cryptoService.SetMasterKeyAsync(newMasterKey);
|
await _cryptoService.SetMasterKeyAsync(newMasterKey);
|
||||||
|
|
||||||
var (newUserKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync(newMasterKey);
|
var (newUserKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync(
|
||||||
|
newMasterKey,
|
||||||
|
await _cryptoService.MakeUserKeyAsync());
|
||||||
|
|
||||||
await _cryptoService.SetUserKeyAsync(newUserKey);
|
await _cryptoService.SetUserKeyAsync(newUserKey);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _apiService.PostUserKeyToKeyConnector(tokenResponse.KeyConnectorUrl, keyConnectorRequest);
|
await _apiService.PostMasterKeyToKeyConnector(tokenResponse.KeyConnectorUrl, keyConnectorRequest);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -115,7 +117,7 @@ namespace Bit.Core.Services
|
|||||||
EncryptedPrivateKey = newProtectedPrivateKey.EncryptedString
|
EncryptedPrivateKey = newProtectedPrivateKey.EncryptedString
|
||||||
};
|
};
|
||||||
var setPasswordRequest = new SetKeyConnectorKeyRequest(
|
var setPasswordRequest = new SetKeyConnectorKeyRequest(
|
||||||
newProtectedPrivateKey.EncryptedString, keys, tokenResponse.KdfConfig, orgId
|
newProtectedUserKey.EncryptedString, keys, tokenResponse.KdfConfig, orgId
|
||||||
);
|
);
|
||||||
await _apiService.PostSetKeyConnectorKey(setPasswordRequest);
|
await _apiService.PostSetKeyConnectorKey(setPasswordRequest);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user