1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-17 08:43:21 +00:00

[SG-174] Login with Device Request - Mobile (#2167)

* [SG-174] Add new login request services to Api

* [SG-174] Fix typo

* [SG-174] Enable login with device button.

* [SG-174] Add new login request page and viewmodel

* [SG-174] Add new text resources

* [SG-174] Add new RSA Decrypt method with string param

* [SG-174] Change create login request method

* [SG-174] Add new method to auth service to login passwordless

* [SG-174] Refactor login helper method to work with passwordless

* [SG-174] Fix service registration

* [SG-174] Update token request to support passwordless

* [SG-174] Update Api service with passwordless methods

* [SG-174] Fix App csproj references

* [SG-174] Remove unnecessary argument

* [SG-174] dotnet format

* [SG-174] Fixed iOS Extensions

* [SG-174] Change Command to ICommand

* [SG-174] Change Gesture Recognizer to Command

* [SG-174] Fix close action

* [SG-174] Code format

* [SG-174] Fix android frame shadow bug

* [SG-174] PR fixes
This commit is contained in:
André Bispo
2022-11-09 16:25:48 +00:00
committed by GitHub
parent 04ed47d545
commit 9ae269dd57
25 changed files with 618 additions and 15 deletions

View File

@@ -24,8 +24,8 @@ namespace Bit.Core.Services
private readonly IPlatformUtilsService _platformUtilsService;
private readonly IMessagingService _messagingService;
private readonly IKeyConnectorService _keyConnectorService;
private readonly IPasswordGenerationService _passwordGenerationService;
private readonly bool _setCryptoKeys;
private SymmetricCryptoKey _key;
public AuthService(
@@ -40,6 +40,7 @@ namespace Bit.Core.Services
IMessagingService messagingService,
IVaultTimeoutService vaultTimeoutService,
IKeyConnectorService keyConnectorService,
IPasswordGenerationService passwordGenerationService,
bool setCryptoKeys = true)
{
_cryptoService = cryptoService;
@@ -52,6 +53,7 @@ namespace Bit.Core.Services
_platformUtilsService = platformUtilsService;
_messagingService = messagingService;
_keyConnectorService = keyConnectorService;
_passwordGenerationService = passwordGenerationService;
_setCryptoKeys = setCryptoKeys;
TwoFactorProviders = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
@@ -137,6 +139,14 @@ namespace Bit.Core.Services
null, captchaToken);
}
public async Task<AuthResult> LogInPasswordlessAsync(string email, string accessCode, string authRequestId, byte[] decryptionKey, string userKeyCiphered, string localHashedPasswordCiphered)
{
var decKey = await _cryptoService.RsaDecryptAsync(userKeyCiphered, decryptionKey);
var decPasswordHash = await _cryptoService.RsaDecryptAsync(localHashedPasswordCiphered, decryptionKey);
return await LogInHelperAsync(email, accessCode, Encoding.UTF8.GetString(decPasswordHash), null, null, null, new SymmetricCryptoKey(decKey), null, null,
null, null, authRequestId: authRequestId);
}
public async Task<AuthResult> LogInSsoAsync(string code, string codeVerifier, string redirectUrl, string orgId)
{
SelectedTwoFactorProviderType = null;
@@ -286,7 +296,7 @@ namespace Bit.Core.Services
private async Task<AuthResult> LogInHelperAsync(string email, string hashedPassword, string localHashedPassword,
string code, string codeVerifier, string redirectUrl, SymmetricCryptoKey key,
TwoFactorProviderType? twoFactorProvider = null, string twoFactorToken = null, bool? remember = null,
string captchaToken = null, string orgId = null)
string captchaToken = null, string orgId = null, string authRequestId = null)
{
var storedTwoFactorToken = await _tokenService.GetTwoFactorTokenAsync(email);
var appId = await _appIdService.GetAppIdAsync();
@@ -322,6 +332,10 @@ namespace Bit.Core.Services
request = new TokenRequest(emailPassword, codeCodeVerifier, TwoFactorProviderType.Remember,
storedTwoFactorToken, false, captchaToken, deviceRequest);
}
else if (authRequestId != null)
{
request = new TokenRequest(emailPassword, null, null, null, false, null, deviceRequest, authRequestId);
}
else
{
request = new TokenRequest(emailPassword, codeCodeVerifier, null, null, false, captchaToken, deviceRequest);
@@ -476,6 +490,11 @@ namespace Bit.Core.Services
return await _apiService.GetAuthRequestAsync(id);
}
public async Task<PasswordlessLoginResponse> GetPasswordlessLoginResponseAsync(string id, string accessCode)
{
return await _apiService.GetAuthResponseAsync(id, accessCode);
}
public async Task<PasswordlessLoginResponse> PasswordlessLoginAsync(string id, string pubKey, bool requestApproved)
{
var publicKey = CoreHelpers.Base64UrlDecode(pubKey);
@@ -485,5 +504,25 @@ namespace Bit.Core.Services
var deviceId = await _appIdService.GetAppIdAsync();
return await _apiService.PutAuthRequestAsync(id, encryptedKey.EncryptedString, encryptedMasterPassword.EncryptedString, deviceId, requestApproved);
}
public async Task<PasswordlessLoginResponse> PasswordlessCreateLoginRequestAsync(string email)
{
var deviceId = await _appIdService.GetAppIdAsync();
var keyPair = await _cryptoFunctionService.RsaGenerateKeyPairAsync(2048);
var generatedFingerprintPhrase = await _cryptoService.GetFingerprintAsync(email, keyPair.Item1);
var fingerprintPhrase = string.Join("-", generatedFingerprintPhrase);
var publicB64 = Convert.ToBase64String(keyPair.Item1);
var accessCode = await _passwordGenerationService.GeneratePasswordAsync(new PasswordGenerationOptions(true) { Length = 25 });
var passwordlessCreateLoginRequest = new PasswordlessCreateLoginRequest(email, publicB64, deviceId, accessCode, AuthRequestType.AuthenticateAndUnlock, fingerprintPhrase);
var response = await _apiService.PostCreateRequestAsync(passwordlessCreateLoginRequest);
if (response != null)
{
response.RequestKeyPair = keyPair;
response.RequestAccessCode = accessCode;
}
return response;
}
}
}