1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-05 23:53:33 +00:00

[PM-2293] Trust device after admin request login.

This commit is contained in:
André Bispo
2023-07-10 15:34:54 +01:00
parent a15269bafe
commit ce55750e60
10 changed files with 53 additions and 7 deletions

View File

@@ -46,7 +46,6 @@ namespace Bit.App.Pages
await Navigation.PushModalAsync(new NavigationPage(page));
}
private async Task StartLoginWithDeviceAsync()
{
var page = new LoginPasswordlessRequestPage(_vm.Email, AuthRequestType.AuthenticateAndUnlock, _appOptions);

View File

@@ -25,6 +25,7 @@ namespace Bit.App.Pages
private string _email;
private readonly IStateService _stateService;
private readonly IApiService _apiService;
private IDeviceTrustCryptoService _deviceTrustCryptoService;
public ICommand ApproveWithMyOtherDeviceCommand { get; }
public ICommand RequestAdminApprovalCommand { get; }
@@ -40,18 +41,19 @@ namespace Bit.App.Pages
{
_stateService = ServiceContainer.Resolve<IStateService>();
_apiService = ServiceContainer.Resolve<IApiService>();
_deviceTrustCryptoService = ServiceContainer.Resolve<IDeviceTrustCryptoService>();
PageTitle = AppResources.LoggedIn;
ApproveWithMyOtherDeviceCommand = new AsyncCommand(() => Device.InvokeOnMainThreadAsync(LogInWithDeviceAction),
ApproveWithMyOtherDeviceCommand = new AsyncCommand(() => CheckDeviceTrustAndInvoke(LogInWithDeviceAction),
onException: ex => HandleException(ex),
allowsMultipleExecutions: false);
RequestAdminApprovalCommand = new AsyncCommand(() => Device.InvokeOnMainThreadAsync(RequestAdminApprovalAction),
RequestAdminApprovalCommand = new AsyncCommand(() => CheckDeviceTrustAndInvoke(RequestAdminApprovalAction),
onException: ex => HandleException(ex),
allowsMultipleExecutions: false);
ApproveWithMasterPasswordCommand = new AsyncCommand(() => Device.InvokeOnMainThreadAsync(LogInWithMasterPassword),
ApproveWithMasterPasswordCommand = new AsyncCommand(() => CheckDeviceTrustAndInvoke(LogInWithMasterPassword),
onException: ex => HandleException(ex),
allowsMultipleExecutions: false);
@@ -106,8 +108,8 @@ namespace Bit.App.Pages
try
{
var decryptOptions = await _stateService.GetAccountDecryptionOptions();
RequestAdminApprovalEnabled = decryptOptions.TrustedDeviceOption.HasAdminApproval;
ApproveWithMasterPasswordEnabled = decryptOptions.HasMasterPassword;
RequestAdminApprovalEnabled = decryptOptions != null && decryptOptions.TrustedDeviceOption != null && decryptOptions.TrustedDeviceOption.HasAdminApproval;
ApproveWithMasterPasswordEnabled = decryptOptions != null && decryptOptions.HasMasterPassword;
}
catch (Exception ex)
{
@@ -126,6 +128,12 @@ namespace Bit.App.Pages
// TODO: Change this expression to, Appear if the browser is trusted and shared the key with the app
ContinueEnabled = !RequestAdminApprovalEnabled && !ApproveWithMasterPasswordEnabled && !ApproveWithMyOtherDeviceEnabled;
}
private async Task CheckDeviceTrustAndInvoke(Action action)
{
await _deviceTrustCryptoService.SetUserTrustDeviceChoiceForDecryptionAsync(RememberThisDevice);
await Device.InvokeOnMainThreadAsync(action);
}
}
}

View File

@@ -45,6 +45,7 @@
AutomationId="FingerprintPhraseValue" />
<Label
Text="{u:I18n ResendNotification}"
IsVisible="{Binding ResendNotificationVisible}"
StyleClass="text-md"
HorizontalOptions="Start"
Margin="0,40,0,0"

View File

@@ -33,6 +33,7 @@ namespace Bit.App.Pages
private IPlatformUtilsService _platformUtilsService;
private IEnvironmentService _environmentService;
private ILogger _logger;
private IDeviceTrustCryptoService _deviceTrustCryptoService;
protected override II18nService i18nService => _i18nService;
protected override IEnvironmentService environmentService => _environmentService;
@@ -59,6 +60,7 @@ namespace Bit.App.Pages
_i18nService = ServiceContainer.Resolve<II18nService>();
_stateService = ServiceContainer.Resolve<IStateService>();
_logger = ServiceContainer.Resolve<ILogger>();
_deviceTrustCryptoService = ServiceContainer.Resolve<IDeviceTrustCryptoService>();
PageTitle = AppResources.LogInWithAnotherDevice;
@@ -162,10 +164,13 @@ namespace Bit.App.Pages
nameof(Tittle),
nameof(SubTittle),
nameof(Description),
nameof(OtherOptions)
nameof(OtherOptions),
nameof(ResendNotificationVisible)
});
}
public bool ResendNotificationVisible => AuthRequestType == AuthRequestType.AuthenticateAndUnlock;
public void StartCheckLoginRequestStatus()
{
try
@@ -231,6 +236,7 @@ namespace Bit.App.Pages
else
{
_syncService.FullSyncAsync(true).FireAndForget();
await _deviceTrustCryptoService.TrustDeviceAsync();
LogInSuccessAction?.Invoke();
}
}

View File

@@ -7,5 +7,7 @@ namespace Bit.Core.Abstractions
{
Task<SymmetricCryptoKey> GetDeviceKeyAsync();
Task<DeviceResponse> TrustDeviceAsync();
Task<bool> GetUserTrustDeviceChoiceForDecryptionAsync();
Task SetUserTrustDeviceChoiceForDecryptionAsync(bool value);
}
}

View File

@@ -179,5 +179,7 @@ namespace Bit.Core.Abstractions
void SetLocale(string locale);
ConfigResponse GetConfigs();
void SetConfigs(ConfigResponse value);
Task<bool> GetUserTrustDeviceChoiceForDecryptionAsync();
Task SetUserTrustDeviceChoiceForDecryptionAsync(bool value);
}
}

View File

@@ -53,6 +53,7 @@
public const string AppLocaleKey = "appLocale";
public const string ClearSensitiveFields = "clearSensitiveFields";
public const string ForceUpdatePassword = "forceUpdatePassword";
public const string RememberDeviceTde = "rememberDeviceTde";
public const int SelectFileRequestCode = 42;
public const int SelectFilePermissionRequestCode = 43;
public const int SaveFileRequestCode = 44;

View File

@@ -43,6 +43,11 @@ namespace Bit.Core.Services
public async Task<DeviceResponse> TrustDeviceAsync()
{
if(!await GetUserTrustDeviceChoiceForDecryptionAsync())
{
return null;
}
// Attempt to get user key
var userKey = await _cryptoService.GetEncKeyAsync();
if (userKey == null)
@@ -77,5 +82,15 @@ namespace Bit.Core.Services
var randomBytes = await _cryptoFunctionService.RandomBytesAsync(DEVICE_KEY_SIZE);
return new SymmetricCryptoKey(randomBytes);
}
public async Task<bool> GetUserTrustDeviceChoiceForDecryptionAsync()
{
return await _stateService.GetUserTrustDeviceChoiceForDecryptionAsync();
}
public async Task SetUserTrustDeviceChoiceForDecryptionAsync(bool value)
{
await _stateService.SetUserTrustDeviceChoiceForDecryptionAsync(value);
}
}
}

View File

@@ -1298,6 +1298,16 @@ namespace Bit.Core.Services
))?.Profile?.UserDecryptionOptions;
}
public async Task<bool> GetUserTrustDeviceChoiceForDecryptionAsync()
{
return await _storageMediatorService.GetAsync<bool>(Constants.RememberDeviceTde, true);
}
public async Task SetUserTrustDeviceChoiceForDecryptionAsync(bool value)
{
await _storageMediatorService.SaveAsync(Constants.RememberDeviceTde, true);
}
public ConfigResponse GetConfigs()
{
return _storageMediatorService.Get<ConfigResponse>(Constants.ConfigsKey);

View File

@@ -88,6 +88,7 @@ namespace Bit.Core.Utilities
cryptoService);
var usernameGenerationService = new UsernameGenerationService(cryptoService, apiService, stateService);
var configService = new ConfigService(apiService, stateService, logger);
var deviceTrustCryptoService = new DeviceTrustCryptoService(apiService, appIdService, cryptoFunctionService, cryptoService, stateService);
Register<IConditionedAwaiterManager>(conditionedRunner);
Register<ITokenService>("tokenService", tokenService);
@@ -114,6 +115,7 @@ namespace Bit.Core.Utilities
Register<IUserVerificationService>("userVerificationService", userVerificationService);
Register<IUsernameGenerationService>(usernameGenerationService);
Register<IConfigService>(configService);
Register<IDeviceTrustCryptoService>(deviceTrustCryptoService);
}
public static void Register<T>(string serviceName, T obj)