mirror of
https://github.com/bitwarden/android.git
synced 2024-12-24 01:48:25 +03:00
two-factor other methods switching and send email
This commit is contained in:
parent
56075cb7d9
commit
74fba486bd
11 changed files with 208 additions and 188 deletions
|
@ -51,7 +51,7 @@ namespace Bit.Android
|
|||
|
||||
Console.WriteLine("A OnCreate");
|
||||
Window.SetSoftInputMode(SoftInput.StateHidden);
|
||||
//Window.AddFlags(WindowManagerFlags.Secure);
|
||||
Window.AddFlags(WindowManagerFlags.Secure);
|
||||
|
||||
var appIdService = Resolver.Resolve<IAppIdService>();
|
||||
var authService = Resolver.Resolve<IAuthService>();
|
||||
|
|
|
@ -234,6 +234,7 @@ namespace Bit.Android
|
|||
container.RegisterSingleton<ICipherApiRepository, CipherApiRepository>();
|
||||
container.RegisterSingleton<ISettingsRepository, SettingsRepository>();
|
||||
container.RegisterSingleton<ISettingsApiRepository, SettingsApiRepository>();
|
||||
container.RegisterSingleton<ITwoFactorApiRepository, TwoFactorApiRepository>();
|
||||
|
||||
// Other
|
||||
container.RegisterSingleton(CrossSettings.Current);
|
||||
|
|
10
src/App/Abstractions/Repositories/ITwoFactorApiRepository.cs
Normal file
10
src/App/Abstractions/Repositories/ITwoFactorApiRepository.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Api;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ITwoFactorApiRepository
|
||||
{
|
||||
Task<ApiResult> PostSendEmailLoginAsync(TwoFactorEmailRequest requestObj);
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Abstractions\Repositories\ITwoFactorApiRepository.cs" />
|
||||
<Compile Include="Abstractions\Repositories\ISettingsApiRepository.cs" />
|
||||
<Compile Include="Abstractions\Repositories\IAccountsApiRepository.cs" />
|
||||
<Compile Include="Abstractions\Repositories\IDeviceApiRepository.cs" />
|
||||
|
@ -97,6 +98,7 @@
|
|||
<Compile Include="Models\Api\Request\DeviceTokenRequest.cs" />
|
||||
<Compile Include="Models\Api\Request\FolderRequest.cs" />
|
||||
<Compile Include="Models\Api\Request\DeviceRequest.cs" />
|
||||
<Compile Include="Models\Api\Request\TwoFactorEmailRequest.cs" />
|
||||
<Compile Include="Models\Api\Request\RegisterRequest.cs" />
|
||||
<Compile Include="Models\Api\Request\LoginRequest.cs" />
|
||||
<Compile Include="Models\Api\Request\PasswordHintRequest.cs" />
|
||||
|
@ -135,7 +137,6 @@
|
|||
<Compile Include="Pages\HomePage.cs" />
|
||||
<Compile Include="Pages\Lock\BaseLockPage.cs" />
|
||||
<Compile Include="Pages\Lock\LockPasswordPage.cs" />
|
||||
<Compile Include="Pages\TwoFactorMethodsPage.cs" />
|
||||
<Compile Include="Pages\LoginTwoFactorPage.cs" />
|
||||
<Compile Include="Pages\PasswordHintPage.cs" />
|
||||
<Compile Include="Pages\RegisterPage.cs" />
|
||||
|
@ -159,6 +160,7 @@
|
|||
<Compile Include="Pages\Vault\VaultAutofillListLoginsPage.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Abstractions\Repositories\ILoginRepository.cs" />
|
||||
<Compile Include="Repositories\TwoFactorApiRepository.cs" />
|
||||
<Compile Include="Repositories\SettingsApiRepository.cs" />
|
||||
<Compile Include="Repositories\ApiRepository.cs" />
|
||||
<Compile Include="Repositories\AccountsApiRepository.cs" />
|
||||
|
|
8
src/App/Models/Api/Request/TwoFactorEmailRequest.cs
Normal file
8
src/App/Models/Api/Request/TwoFactorEmailRequest.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class TwoFactorEmailRequest
|
||||
{
|
||||
public string Email { get; set; }
|
||||
public string MasterPasswordHash { get; set; }
|
||||
}
|
||||
}
|
|
@ -11,7 +11,6 @@ using Bit.App.Models;
|
|||
using Bit.App.Utilities;
|
||||
using Bit.App.Enums;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using FFImageLoading.Forms;
|
||||
|
||||
|
@ -25,12 +24,13 @@ namespace Bit.App.Pages
|
|||
private ISyncService _syncService;
|
||||
private IDeviceInfoService _deviceInfoService;
|
||||
private IGoogleAnalyticsService _googleAnalyticsService;
|
||||
private ITwoFactorApiRepository _twoFactorApiRepository;
|
||||
private IPushNotification _pushNotification;
|
||||
private readonly string _email;
|
||||
private readonly string _masterPasswordHash;
|
||||
private readonly SymmetricCryptoKey _key;
|
||||
private readonly Dictionary<TwoFactorProviderType, Dictionary<string, object>> _providers;
|
||||
private readonly TwoFactorProviderType? _providerType;
|
||||
private TwoFactorProviderType? _providerType;
|
||||
private readonly FullLoginResult _result;
|
||||
|
||||
public LoginTwoFactorPage(string email, FullLoginResult result, TwoFactorProviderType? type = null)
|
||||
|
@ -49,11 +49,10 @@ namespace Bit.App.Pages
|
|||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||
_syncService = Resolver.Resolve<ISyncService>();
|
||||
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
|
||||
_twoFactorApiRepository = Resolver.Resolve<ITwoFactorApiRepository>();
|
||||
_pushNotification = Resolver.Resolve<IPushNotification>();
|
||||
|
||||
Init();
|
||||
|
||||
SubscribeYubiKey(true);
|
||||
}
|
||||
|
||||
public FormEntryCell TokenCell { get; set; }
|
||||
|
@ -61,6 +60,13 @@ namespace Bit.App.Pages
|
|||
|
||||
private void Init()
|
||||
{
|
||||
SubscribeYubiKey(true);
|
||||
if(_providers.Count > 1)
|
||||
{
|
||||
var sendEmailTask = SendEmailAsync(false);
|
||||
}
|
||||
|
||||
ToolbarItems.Clear();
|
||||
var scrollView = new ScrollView();
|
||||
|
||||
var anotherMethodButton = new ExtendedButton
|
||||
|
@ -70,7 +76,8 @@ namespace Bit.App.Pages
|
|||
Margin = new Thickness(15, 0, 15, 25),
|
||||
Command = new Command(() => AnotherMethodAsync()),
|
||||
Uppercase = false,
|
||||
BackgroundColor = Color.Transparent
|
||||
BackgroundColor = Color.Transparent,
|
||||
VerticalOptions = LayoutOptions.Start
|
||||
};
|
||||
|
||||
var instruction = new Label
|
||||
|
@ -107,7 +114,7 @@ namespace Bit.App.Pages
|
|||
var continueToolbarItem = new ToolbarItem(AppResources.Continue, null, async () =>
|
||||
{
|
||||
var token = TokenCell?.Entry.Text.Trim().Replace(" ", "");
|
||||
await LogInAsync(token, RememberCell.On);
|
||||
await LogInAsync(token);
|
||||
}, ToolbarItemOrder.Default, 0);
|
||||
|
||||
var padding = Helpers.OnPlatform(
|
||||
|
@ -130,7 +137,7 @@ namespace Bit.App.Pages
|
|||
|
||||
var layout = new StackLayout
|
||||
{
|
||||
Children = { instruction, table, anotherMethodButton },
|
||||
Children = { instruction, table },
|
||||
Spacing = 0
|
||||
};
|
||||
|
||||
|
@ -140,27 +147,24 @@ namespace Bit.App.Pages
|
|||
{
|
||||
case TwoFactorProviderType.Authenticator:
|
||||
instruction.Text = "Enter the 6 digit verification code from your authenticator app.";
|
||||
layout.Children.Add(instruction);
|
||||
layout.Children.Add(table);
|
||||
layout.Children.Add(anotherMethodButton);
|
||||
break;
|
||||
case TwoFactorProviderType.Email:
|
||||
var emailParams = _providers[TwoFactorProviderType.Email];
|
||||
var redactedEmail = emailParams["Email"].ToString();
|
||||
|
||||
instruction.Text = "Enter the 6 digit verification code from your authenticator app.";
|
||||
instruction.Text = $"Enter the 6 digit verification code that was emailed to {redactedEmail}.";
|
||||
var resendEmailButton = new ExtendedButton
|
||||
{
|
||||
Text = $"Enter the 6 digit verification code that was emailed to {redactedEmail}.",
|
||||
Text = "Send verification code email again",
|
||||
Style = (Style)Application.Current.Resources["btn-primaryAccent"],
|
||||
Margin = new Thickness(15, 0, 15, 25),
|
||||
Command = new Command(() => SendEmail()),
|
||||
Margin = new Thickness(15, 0, 15, 0),
|
||||
Command = new Command(async () => await SendEmailAsync(true)),
|
||||
Uppercase = false,
|
||||
BackgroundColor = Color.Transparent
|
||||
BackgroundColor = Color.Transparent,
|
||||
VerticalOptions = LayoutOptions.Start
|
||||
};
|
||||
|
||||
layout.Children.Add(instruction);
|
||||
layout.Children.Add(table);
|
||||
layout.Children.Add(resendEmailButton);
|
||||
layout.Children.Add(anotherMethodButton);
|
||||
break;
|
||||
|
@ -184,15 +188,30 @@ namespace Bit.App.Pages
|
|||
{
|
||||
Uri = $"http://192.168.1.6:4001/duo-mobile.html?host={host}&request={req}",
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand,
|
||||
VerticalOptions = LayoutOptions.FillAndExpand
|
||||
VerticalOptions = LayoutOptions.FillAndExpand,
|
||||
MinimumHeightRequest = 400
|
||||
};
|
||||
webView.RegisterAction(async (sig) =>
|
||||
{
|
||||
await LogInAsync(sig, false);
|
||||
await LogInAsync(sig);
|
||||
});
|
||||
|
||||
var table = new TwoFactorTable(
|
||||
new TableSection(" ")
|
||||
{
|
||||
RememberCell
|
||||
});
|
||||
|
||||
var layout = new StackLayout
|
||||
{
|
||||
Children = { webView, table, anotherMethodButton },
|
||||
Spacing = 0
|
||||
};
|
||||
|
||||
scrollView.Content = layout;
|
||||
|
||||
Title = "Duo";
|
||||
Content = webView;
|
||||
Content = scrollView;
|
||||
}
|
||||
else if(_providerType == TwoFactorProviderType.YubiKey)
|
||||
{
|
||||
|
@ -254,28 +273,99 @@ namespace Bit.App.Pages
|
|||
|
||||
private async void AnotherMethodAsync()
|
||||
{
|
||||
await Navigation.PushForDeviceAsync(new TwoFactorMethodsPage(_email, _result));
|
||||
var beforeProviderType = _providerType;
|
||||
|
||||
var options = new List<string>();
|
||||
if(_providers.ContainsKey(TwoFactorProviderType.Authenticator))
|
||||
{
|
||||
options.Add("Authenticator App");
|
||||
}
|
||||
|
||||
if(_providers.ContainsKey(TwoFactorProviderType.Duo))
|
||||
{
|
||||
options.Add("Duo");
|
||||
}
|
||||
|
||||
if(_providers.ContainsKey(TwoFactorProviderType.YubiKey))
|
||||
{
|
||||
var nfcKey = _providers[TwoFactorProviderType.YubiKey].ContainsKey("Nfc") &&
|
||||
(bool)_providers[TwoFactorProviderType.YubiKey]["Nfc"];
|
||||
if(_deviceInfoService.NfcEnabled || nfcKey)
|
||||
{
|
||||
options.Add("YubiKey NFC Security Key");
|
||||
}
|
||||
}
|
||||
|
||||
if(_providers.ContainsKey(TwoFactorProviderType.Email))
|
||||
{
|
||||
options.Add("Email");
|
||||
}
|
||||
|
||||
options.Add("Recovery Code");
|
||||
|
||||
var selection = await DisplayActionSheet("Two-step Login Options", AppResources.Cancel, null, options.ToArray());
|
||||
if(selection == "Authenticator App")
|
||||
{
|
||||
_providerType = TwoFactorProviderType.Authenticator;
|
||||
}
|
||||
else if(selection == "Duo")
|
||||
{
|
||||
_providerType = TwoFactorProviderType.Duo;
|
||||
}
|
||||
else if(selection == "YubiKey NFC Security Key")
|
||||
{
|
||||
_providerType = TwoFactorProviderType.YubiKey;
|
||||
}
|
||||
else if(selection == "Email")
|
||||
{
|
||||
_providerType = TwoFactorProviderType.Email;
|
||||
}
|
||||
else if(selection == "Recovery Code")
|
||||
{
|
||||
Device.OpenUri(new Uri("https://help.bitwarden.com/article/lost-two-step-device/"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(beforeProviderType != _providerType)
|
||||
{
|
||||
Init();
|
||||
ListenYubiKey(false, beforeProviderType == TwoFactorProviderType.YubiKey);
|
||||
ListenYubiKey(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendEmail()
|
||||
private async Task SendEmailAsync(bool doToast)
|
||||
{
|
||||
if(_providerType != TwoFactorProviderType.Email)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
var response = await _twoFactorApiRepository.PostSendEmailLoginAsync(new Models.Api.TwoFactorEmailRequest
|
||||
{
|
||||
Email = _email,
|
||||
MasterPasswordHash = _masterPasswordHash
|
||||
});
|
||||
|
||||
private void Recover()
|
||||
{
|
||||
Device.OpenUri(new Uri("https://help.bitwarden.com/article/lost-two-step-device/"));
|
||||
if(response.Succeeded && doToast)
|
||||
{
|
||||
_userDialogs.Toast("Verification email sent.");
|
||||
}
|
||||
else if(!response.Succeeded)
|
||||
{
|
||||
_userDialogs.Alert("Could not send verification email. Try again.");
|
||||
}
|
||||
}
|
||||
|
||||
private async void Entry_Completed(object sender, EventArgs e)
|
||||
{
|
||||
var token = TokenCell.Entry.Text.Trim().Replace(" ", "");
|
||||
await LogInAsync(token, RememberCell.On);
|
||||
await LogInAsync(token);
|
||||
}
|
||||
|
||||
private async Task LogInAsync(string token, bool remember)
|
||||
private async Task LogInAsync(string token)
|
||||
{
|
||||
if(_lastAction.LastActionWasRecent())
|
||||
if(!_providerType.HasValue || _lastAction.LastActionWasRecent())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -288,8 +378,8 @@ namespace Bit.App.Pages
|
|||
return;
|
||||
}
|
||||
|
||||
_userDialogs.ShowLoading(AppResources.ValidatingCode, MaskType.Black);
|
||||
var response = await _authService.TokenPostTwoFactorAsync(_providerType.Value, token, remember,
|
||||
_userDialogs.ShowLoading(string.Concat(AppResources.Validating, "..."), MaskType.Black);
|
||||
var response = await _authService.TokenPostTwoFactorAsync(_providerType.Value, token, RememberCell.On,
|
||||
_email, _masterPasswordHash, _key);
|
||||
_userDialogs.HideLoading();
|
||||
if(!response.Success)
|
||||
|
@ -299,7 +389,7 @@ namespace Bit.App.Pages
|
|||
return;
|
||||
}
|
||||
|
||||
_googleAnalyticsService.TrackAppEvent("LoggedIn From Two-step");
|
||||
_googleAnalyticsService.TrackAppEvent("LoggedIn From Two-step", _providerType.Value.ToString());
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
|
@ -320,11 +410,6 @@ namespace Bit.App.Pages
|
|||
|
||||
if(_providers != null)
|
||||
{
|
||||
if(_providers.Count == 1)
|
||||
{
|
||||
return _providers.First().Key;
|
||||
}
|
||||
|
||||
foreach(var p in _providers)
|
||||
{
|
||||
switch(p.Key)
|
||||
|
@ -348,7 +433,8 @@ namespace Bit.App.Pages
|
|||
}
|
||||
break;
|
||||
case TwoFactorProviderType.YubiKey:
|
||||
if(!_deviceInfoService.NfcEnabled)
|
||||
var nfcKey = p.Value.ContainsKey("Nfc") && (bool)p.Value["Nfc"];
|
||||
if(!_deviceInfoService.NfcEnabled || !nfcKey)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -364,9 +450,9 @@ namespace Bit.App.Pages
|
|||
return provider;
|
||||
}
|
||||
|
||||
private void ListenYubiKey(bool listen)
|
||||
private void ListenYubiKey(bool listen, bool overrideCheck = false)
|
||||
{
|
||||
if(_providerType == TwoFactorProviderType.YubiKey)
|
||||
if(_providerType == TwoFactorProviderType.YubiKey || overrideCheck)
|
||||
{
|
||||
MessagingCenter.Send(Application.Current, "ListenYubiKeyOTP", listen);
|
||||
}
|
||||
|
@ -391,7 +477,7 @@ namespace Bit.App.Pages
|
|||
MessagingCenter.Unsubscribe<Application, string>(Application.Current, "GotYubiKeyOTP");
|
||||
if(_providerType == TwoFactorProviderType.YubiKey)
|
||||
{
|
||||
await LogInAsync(otp, RememberCell.On);
|
||||
await LogInAsync(otp);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
using System;
|
||||
using Bit.App.Controls;
|
||||
using Xamarin.Forms;
|
||||
using Bit.App.Models;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
public class TwoFactorMethodsPage : ExtendedContentPage
|
||||
{
|
||||
private readonly string _email;
|
||||
private readonly FullLoginResult _result;
|
||||
|
||||
public TwoFactorMethodsPage(string email, FullLoginResult result)
|
||||
: base(updateActivity: false)
|
||||
{
|
||||
_email = email;
|
||||
_result = result;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
public ExtendedTextCell AuthenticatorCell { get; set; }
|
||||
public ExtendedTextCell EmailCell { get; set; }
|
||||
public ExtendedTextCell DuoCell { get; set; }
|
||||
public ExtendedTextCell RecoveryCell { get; set; }
|
||||
|
||||
private void Init()
|
||||
{
|
||||
var section = new TableSection(" ");
|
||||
|
||||
if(_result.TwoFactorProviders.ContainsKey(Enums.TwoFactorProviderType.Authenticator))
|
||||
{
|
||||
AuthenticatorCell = new ExtendedTextCell
|
||||
{
|
||||
Text = "Authenticator App",
|
||||
Detail = "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes."
|
||||
};
|
||||
section.Add(AuthenticatorCell);
|
||||
}
|
||||
|
||||
if(_result.TwoFactorProviders.ContainsKey(Enums.TwoFactorProviderType.Duo))
|
||||
{
|
||||
DuoCell = new ExtendedTextCell
|
||||
{
|
||||
Text = "Duo",
|
||||
Detail = "Use duo."
|
||||
};
|
||||
section.Add(DuoCell);
|
||||
}
|
||||
|
||||
if(_result.TwoFactorProviders.ContainsKey(Enums.TwoFactorProviderType.Email))
|
||||
{
|
||||
EmailCell = new ExtendedTextCell
|
||||
{
|
||||
Text = "Email",
|
||||
Detail = "Verification codes will be emailed to you."
|
||||
};
|
||||
section.Add(EmailCell);
|
||||
}
|
||||
|
||||
RecoveryCell = new ExtendedTextCell
|
||||
{
|
||||
Text = "Recovery Code",
|
||||
Detail = "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account."
|
||||
};
|
||||
section.Add(RecoveryCell);
|
||||
|
||||
var table = new ExtendedTableView
|
||||
{
|
||||
EnableScrolling = true,
|
||||
Intent = TableIntent.Settings,
|
||||
HasUnevenRows = true,
|
||||
Root = new TableRoot
|
||||
{
|
||||
section
|
||||
}
|
||||
};
|
||||
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
table.RowHeight = -1;
|
||||
table.EstimatedRowHeight = 100;
|
||||
}
|
||||
|
||||
Title = "Two-step Login Options";
|
||||
Content = table;
|
||||
}
|
||||
|
||||
protected override void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
if(AuthenticatorCell != null)
|
||||
{
|
||||
AuthenticatorCell.Tapped += AuthenticatorCell_Tapped;
|
||||
}
|
||||
if(DuoCell != null)
|
||||
{
|
||||
DuoCell.Tapped += DuoCell_Tapped;
|
||||
}
|
||||
if(EmailCell != null)
|
||||
{
|
||||
EmailCell.Tapped += EmailCell_Tapped;
|
||||
}
|
||||
RecoveryCell.Tapped += RecoveryCell_Tapped;
|
||||
}
|
||||
|
||||
protected override void OnDisappearing()
|
||||
{
|
||||
base.OnDisappearing();
|
||||
if(AuthenticatorCell != null)
|
||||
{
|
||||
AuthenticatorCell.Tapped -= AuthenticatorCell_Tapped;
|
||||
}
|
||||
if(DuoCell != null)
|
||||
{
|
||||
DuoCell.Tapped -= DuoCell_Tapped;
|
||||
}
|
||||
if(EmailCell != null)
|
||||
{
|
||||
EmailCell.Tapped -= EmailCell_Tapped;
|
||||
}
|
||||
RecoveryCell.Tapped -= RecoveryCell_Tapped;
|
||||
}
|
||||
|
||||
private void AuthenticatorCell_Tapped(object sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void RecoveryCell_Tapped(object sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void EmailCell_Tapped(object sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void DuoCell_Tapped(object sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
53
src/App/Repositories/TwoFactorApiRepository.cs
Normal file
53
src/App/Repositories/TwoFactorApiRepository.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Models.Api;
|
||||
using Plugin.Connectivity.Abstractions;
|
||||
|
||||
namespace Bit.App.Repositories
|
||||
{
|
||||
public class TwoFactorApiRepository : BaseApiRepository, ITwoFactorApiRepository
|
||||
{
|
||||
public TwoFactorApiRepository(
|
||||
IConnectivity connectivity,
|
||||
IHttpService httpService,
|
||||
ITokenService tokenService)
|
||||
: base(connectivity, httpService, tokenService)
|
||||
{ }
|
||||
|
||||
protected override string ApiRoute => "two-factor";
|
||||
|
||||
public virtual async Task<ApiResult> PostSendEmailLoginAsync(TwoFactorEmailRequest requestObj)
|
||||
{
|
||||
if(!Connectivity.IsConnected)
|
||||
{
|
||||
return HandledNotConnected();
|
||||
}
|
||||
|
||||
using(var client = HttpService.ApiClient)
|
||||
{
|
||||
var requestMessage = new TokenHttpRequestMessage(requestObj)
|
||||
{
|
||||
Method = HttpMethod.Post,
|
||||
RequestUri = new Uri(client.BaseAddress, string.Concat(ApiRoute, "/send-email-login")),
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var response = await client.SendAsync(requestMessage).ConfigureAwait(false);
|
||||
if(!response.IsSuccessStatusCode)
|
||||
{
|
||||
return await HandleErrorAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return ApiResult.Success(response.StatusCode);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return HandledWebException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6
src/App/Resources/AppResources.Designer.cs
generated
6
src/App/Resources/AppResources.Designer.cs
generated
|
@ -1943,11 +1943,11 @@ namespace Bit.App.Resources {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Validating code....
|
||||
/// Looks up a localized string similar to Validating.
|
||||
/// </summary>
|
||||
public static string ValidatingCode {
|
||||
public static string Validating {
|
||||
get {
|
||||
return ResourceManager.GetString("ValidatingCode", resourceCulture);
|
||||
return ResourceManager.GetString("Validating", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -728,8 +728,8 @@
|
|||
<data name="UnlockWithPIN" xml:space="preserve">
|
||||
<value>Unlock with PIN Code</value>
|
||||
</data>
|
||||
<data name="ValidatingCode" xml:space="preserve">
|
||||
<value>Validating code...</value>
|
||||
<data name="Validating" xml:space="preserve">
|
||||
<value>Validating</value>
|
||||
<comment>Message shown when interacting with the server</comment>
|
||||
</data>
|
||||
<data name="VerificationCode" xml:space="preserve">
|
||||
|
|
|
@ -280,6 +280,7 @@ namespace Bit.iOS
|
|||
container.RegisterSingleton<ICipherApiRepository, CipherApiRepository>();
|
||||
container.RegisterSingleton<ISettingsRepository, SettingsRepository>();
|
||||
container.RegisterSingleton<ISettingsApiRepository, SettingsApiRepository>();
|
||||
container.RegisterSingleton<ITwoFactorApiRepository, TwoFactorApiRepository>();
|
||||
|
||||
// Other
|
||||
container.RegisterSingleton(CrossConnectivity.Current);
|
||||
|
|
Loading…
Reference in a new issue