bitwarden-android/src/App/Services/AuthService.cs

315 lines
9.8 KiB
C#
Raw Normal View History

2016-05-02 09:52:09 +03:00
using System;
using System.Text;
using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Models.Api;
2016-05-03 00:50:16 +03:00
using Plugin.Settings.Abstractions;
using Bit.App.Models;
using System.Linq;
2017-06-27 23:18:32 +03:00
using Bit.App.Enums;
2016-05-02 09:52:09 +03:00
namespace Bit.App.Services
{
public class AuthService : IAuthService
{
2016-07-19 02:16:27 +03:00
private const string EmailKey = "email";
2016-05-03 00:50:16 +03:00
private const string UserIdKey = "userId";
private const string PreviousUserIdKey = "previousUserId";
2016-06-12 07:49:35 +03:00
private const string PinKey = "pin";
2016-05-02 09:52:09 +03:00
private readonly ISecureStorageService _secureStorage;
private readonly ITokenService _tokenService;
2016-05-03 00:50:16 +03:00
private readonly ISettings _settings;
2016-05-02 09:52:09 +03:00
private readonly ICryptoService _cryptoService;
private readonly IConnectApiRepository _connectApiRepository;
private readonly IAccountsApiRepository _accountsApiRepository;
private readonly IAppIdService _appIdService;
private readonly IDeviceInfoService _deviceInfoService;
2016-05-02 09:52:09 +03:00
2016-07-19 02:16:27 +03:00
private string _email;
2016-05-03 00:50:16 +03:00
private string _userId;
private string _previousUserId;
2016-06-12 07:49:35 +03:00
private string _pin;
2016-05-03 00:50:16 +03:00
2016-05-02 09:52:09 +03:00
public AuthService(
2016-05-03 00:50:16 +03:00
ISecureStorageService secureStorage,
ITokenService tokenService,
2016-05-03 00:50:16 +03:00
ISettings settings,
2016-05-02 09:52:09 +03:00
ICryptoService cryptoService,
IConnectApiRepository connectApiRepository,
IAccountsApiRepository accountsApiRepository,
IAppIdService appIdService,
IDeviceInfoService deviceInfoService)
2016-05-02 09:52:09 +03:00
{
_secureStorage = secureStorage;
_tokenService = tokenService;
2016-05-03 00:50:16 +03:00
_settings = settings;
2016-05-02 09:52:09 +03:00
_cryptoService = cryptoService;
_connectApiRepository = connectApiRepository;
_accountsApiRepository = accountsApiRepository;
_appIdService = appIdService;
_deviceInfoService = deviceInfoService;
2016-05-03 00:50:16 +03:00
}
public string UserId
{
get
{
if(!string.IsNullOrWhiteSpace(_userId))
2016-05-03 00:50:16 +03:00
{
return _userId;
}
var userId = _settings.GetValueOrDefault(UserIdKey, string.Empty);
if(!string.IsNullOrWhiteSpace(userId))
{
_userId = userId;
}
2016-05-03 00:50:16 +03:00
return _userId;
}
set
{
if(value != null)
{
_settings.AddOrUpdateValue(UserIdKey, value);
}
else
{
PreviousUserId = _userId;
2016-05-03 00:50:16 +03:00
_settings.Remove(UserIdKey);
2016-05-02 09:52:09 +03:00
}
2016-06-12 07:49:35 +03:00
_userId = value;
2016-05-02 09:52:09 +03:00
}
}
public string PreviousUserId
{
get
{
if(!string.IsNullOrWhiteSpace(_previousUserId))
{
return _previousUserId;
}
var previousUserId = _settings.GetValueOrDefault(PreviousUserIdKey, string.Empty);
if(!string.IsNullOrWhiteSpace(previousUserId))
{
_previousUserId = previousUserId;
}
return _previousUserId;
}
private set
{
if(value != null)
{
_settings.AddOrUpdateValue(PreviousUserIdKey, value);
_previousUserId = value;
}
}
}
public bool UserIdChanged => PreviousUserId != UserId;
2016-07-19 02:16:27 +03:00
public string Email
{
get
{
if(!string.IsNullOrWhiteSpace(_email))
2016-07-19 02:16:27 +03:00
{
return _email;
}
var email = _settings.GetValueOrDefault(EmailKey, string.Empty);
if(!string.IsNullOrWhiteSpace(email))
{
_email = email;
}
2016-07-19 02:16:27 +03:00
return _email;
}
set
{
if(value != null)
{
_settings.AddOrUpdateValue(EmailKey, value);
}
else
{
_settings.Remove(EmailKey);
}
_email = value;
}
}
2016-05-02 09:52:09 +03:00
public bool IsAuthenticated
{
get
{
return _cryptoService.Key != null &&
!string.IsNullOrWhiteSpace(_tokenService.Token) &&
!string.IsNullOrWhiteSpace(UserId);
2016-07-23 09:17:11 +03:00
}
}
2016-05-02 09:52:09 +03:00
2016-06-12 07:49:35 +03:00
public string PIN
{
get
{
if(_pin != null)
{
return _pin;
}
var pinBytes = _secureStorage.Retrieve(PinKey);
if(pinBytes == null)
{
return null;
}
_pin = Encoding.UTF8.GetString(pinBytes, 0, pinBytes.Length);
return _pin;
}
set
{
if(value != null)
{
var pinBytes = Encoding.UTF8.GetBytes(value);
_secureStorage.Store(PinKey, pinBytes);
}
else
{
_secureStorage.Delete(PinKey);
}
_pin = value;
}
}
public bool BelongsToOrganization(string orgId)
{
return !string.IsNullOrWhiteSpace(orgId) && (_cryptoService.OrgKeys?.ContainsKey(orgId) ?? false);
}
2016-05-03 00:50:16 +03:00
public void LogOut()
{
_tokenService.Token = null;
_tokenService.RefreshToken = null;
2016-05-03 00:50:16 +03:00
UserId = null;
2016-07-19 02:16:27 +03:00
Email = null;
2017-04-20 17:20:50 +03:00
_cryptoService.ClearKeys();
_settings.Remove(Constants.SecurityStamp);
_settings.Remove(Constants.PushLastRegistrationDate);
_settings.Remove(Constants.Locked);
2016-05-03 00:50:16 +03:00
}
public async Task<FullLoginResult> TokenPostAsync(string email, string masterPassword)
2016-05-02 09:52:09 +03:00
{
var result = new FullLoginResult();
var normalizedEmail = email.Trim().ToLower();
var key = _cryptoService.MakeKeyFromPassword(masterPassword, normalizedEmail);
var request = new TokenRequest
{
Email = normalizedEmail,
MasterPasswordHash = _cryptoService.HashPasswordBase64(key, masterPassword),
Device = new DeviceRequest(_appIdService, _deviceInfoService)
};
2017-06-27 23:45:12 +03:00
var twoFactorToken = _tokenService.GetTwoFactorToken(normalizedEmail);
2017-06-27 23:35:29 +03:00
if(!string.IsNullOrWhiteSpace(twoFactorToken))
{
request.Token = twoFactorToken;
request.Provider = TwoFactorProviderType.Remember;
request.Remember = false;
}
var response = await _connectApiRepository.PostTokenAsync(request);
if(!response.Succeeded)
{
result.Success = false;
result.ErrorMessage = response.Errors.FirstOrDefault()?.Message;
return result;
}
result.Success = true;
2017-06-27 23:18:32 +03:00
if(response.Result.TwoFactorProviders2 != null && response.Result.TwoFactorProviders2.Count > 0)
{
result.Key = key;
result.MasterPasswordHash = request.MasterPasswordHash;
2017-06-27 23:18:32 +03:00
result.TwoFactorProviders = response.Result.TwoFactorProviders2;
return result;
}
await ProcessLoginSuccessAsync(key, response.Result);
return result;
}
2017-06-27 23:18:32 +03:00
public async Task<LoginResult> TokenPostTwoFactorAsync(TwoFactorProviderType type, string token, bool remember,
string email, string masterPasswordHash, SymmetricCryptoKey key)
{
var result = new LoginResult();
var request = new TokenRequest
{
2017-06-27 23:18:32 +03:00
Remember = remember,
Email = email.Trim().ToLower(),
MasterPasswordHash = masterPasswordHash,
2017-06-27 23:18:32 +03:00
Token = token,
Provider = type,
Device = new DeviceRequest(_appIdService, _deviceInfoService)
};
var response = await _connectApiRepository.PostTokenAsync(request);
if(!response.Succeeded)
{
result.Success = false;
result.ErrorMessage = response.Errors.FirstOrDefault()?.Message;
return result;
}
result.Success = true;
await ProcessLoginSuccessAsync(key, response.Result);
return result;
}
2017-04-22 21:36:31 +03:00
private async Task ProcessLoginSuccessAsync(SymmetricCryptoKey key, TokenResponse response)
{
2017-06-01 05:47:19 +03:00
if(response.Key != null)
{
2017-06-02 23:53:43 +03:00
_cryptoService.SetEncKey(new CipherString(response.Key));
2017-06-01 05:47:19 +03:00
}
2017-04-20 17:29:18 +03:00
if(response.PrivateKey != null)
{
_cryptoService.SetPrivateKey(new CipherString(response.PrivateKey));
2017-04-20 17:29:18 +03:00
}
_cryptoService.Key = key;
_tokenService.Token = response.AccessToken;
_tokenService.RefreshToken = response.RefreshToken;
UserId = _tokenService.TokenUserId;
Email = _tokenService.TokenEmail;
_settings.AddOrUpdateValue(Constants.LastLoginEmail, Email);
if(response.PrivateKey != null)
{
var profile = await _accountsApiRepository.GetProfileAsync();
if(profile.Succeeded)
{
_cryptoService.SetOrgKeys(profile.Result);
}
}
2017-06-27 23:45:12 +03:00
if(!string.IsNullOrWhiteSpace(response.TwoFactorToken))
{
_tokenService.SetTwoFactorToken(_tokenService.TokenEmail, response.TwoFactorToken);
}
2016-07-23 09:17:11 +03:00
}
2016-05-02 09:52:09 +03:00
}
}