mirror of
https://github.com/bitwarden/mobile
synced 2025-12-21 18:53:29 +00:00
* [PM-1208] Add Device approval options screen. View model waiting for additional logic to be added.
* [PM-1208] Add device related api endpoint. Add AccoundDecryptOptions model and property to user Account.
* [PM-1208] Add continue button and not you option
* [PM-1379] add DeviceTrustCryptoService with establish trust logic (#2535)
* [PM-1379] add DeviceCryptoService with establish trust logic
* PM-1379 update api location and other minor refactors
* pm-1379 fix encoding
* update trusted device keys api call to Put
* [PM-1379] rename DeviceCryptoService to DeviceTrustCryptoService
- refactors to prevent side effects
* [PM-1379] rearrange methods in DeviceTrustCryptoService
* [PM-1379] rearrange methods in abstraction
* [PM-1379] deconstruct tuples
* [PM-1379] remove extra tasks
* [PM-2583] Answer auth request with mp field as null if doesn't have it. (#2609)
* [PM-2287][PM-2289][PM-2293] Approval Options (#2608)
* [PM-2293] Add AuthRequestType to PasswordlessLoginPage.
* [PM-2293] Add Actions to ApproveWithDevicePage
* [PM-2293] Change screen text based on AuthRequestType
* [PM-2293] Refactor AuthRequestType enum. Add label. Remove unnecessary actions.
* [PM-2293] Change boolean variable expression.
* [PM-2293] Trust device after admin request login.
* code format
* [PM-2287] Add trust device to master password unlock. Change trust device method. Remove email from SSO login page.
* [PM-2293] Fix state variable get set.
* [PM-2287][PM-2289][PM-2293] Rename method
* [PM-1201] Change timeout actions available based on hasMasterPassword (#2610)
* [PM-1201] Change timeout actions available based on hasMasterPassword
* [PM-2731] add user key and master key types
* [PM-2713] add new state for new keys and obsolete old ones
- UserKey
- MasterKey
- UserKeyMasterKey (enc UserKey from User Table)
* [PM-271] add UserKey and MasterKey support to crypto service
* [PM-2713] rename key hash to password hash & begin add methods to crypto service
* [PM-2713] continue organizing crypto service
* [PM-2713] more updates to crypto service
* [PM-2713] add new pin methods to state service
* [PM-2713] fix signature of GetUserKeyPin
* [PM-2713] add make user key method to crypto service
* [PM-2713] refresh pin key when setting user key
* [PM-2713] use new MakeMasterKey method
* [PM-2713] add toggle method to crypto service for keys
* [PM-2713] converting calls to new crypto service api
* [PM-2713] add migration for pin on lock screens
* [PM-2713] more conversions to new crypto service api
* [PM-2713] convert cipher service and others to crypto service api
* [PM-2713] More conversions to crypto api
* [PM-2713] use new crypto service api in auth service
* [PM-2713] remove unused cached values in crypto service
* [PM-2713] set decrypt and set user key in login helper
* fix bad merge
* Update crypto service api call to fix build
* [PM-1208] Fix app resource file
* [PM-1208] Fix merge
* [PM-1208] Fix merge
* [PM-2713] optimize async code in crypto service
* [PM-2713] rename password hash to master key hash
* [PM-2713] fix casting issues and pin
* [PM-2713] remove extra comment
* [PM-2713] remove broken casting
* [PM-2297] Login with trusted device (Flow 2) (#2623)
* [PM-2297] Add DecryptUserKeyWithDeviceKey method
* [PM-2297] Add methods to DeviceTrustCryptoService update decryption options model
* [PM-2297] Update account decryption options model
* [PM-2297] Fix TrustedDeviceOption and DeviceResponse model. Change StateService device key get set to have default user id
* [PM-2297] Update navigation to decryption options
* [PM-2297] Add missing action navigations to iOS extensions
* [PM-2297] Fix trust device bug/typo
* [PM-2297] Fix model bug
* [PM-2297] Fix state var crash
* [PM-2297] Add trust device login logic to auth service
* [PM-2297] Refactor auth service key connector code
* [PM-2297] Remove reconciledOptions for deviceKey in state service
* [PM-2297] Remove unnecessary user id params
* [PM-2289] [PM-2293] TDE Login with device Admin Request (#2642)
* [PM-2713] deconstruct new key pair
* [PM-2713] rename PrivateKey methods to UserPrivateKey on crypto service
* [PM-2713] rename PinLockEnum to PinLockType
* [PM-2713] don't pass user key as param when encrypting
* [PM-2713] rename toggle method, don't reset enc user key
* [PM-2713] pr feedback
* [PM-2713] PR feedback
* [PM-2713] rename get pin lock type method
* [PM-2713] revert feedback for build
* [PM-2713] rename state methods
* [PM-2713] combine makeDataEncKey methods
* [PM-2713] consolidate attachment key creation
- also fix ios files missed during symbol rename
* [PM-2713] replace generic with inherited class
* rename account keys to be more descriptive
* [PM-2713] add auto unlock key to mobile
* [PM-1208] Add TDE flows for new users (#2655)
* [PM-1208] Create new user on SSO. Logout if not password is setup or has pending admin auth request.
* [PM-1208] Fix new user UserKey decryption.
* [PM-1208] Add new user continue to vault logic. Auto enrol user on continue.
* [PM-1208] Trust device only if needed
* [PM-1208] Add logic for New User SSO.
* [PM-1208] Add logic for New User SSO (missing file).
* [PM-2713] set user key on set password page
* [PM-2713] set enc user key during kc onboarding
* fix formatting
* [PM-2713] make method async again
- returning null from a task thats not async throws
* [PM-2713] clear service cache when adding new account
* Fix build after merge
* [PM-3313] Fix Android SSO Login (#2663)
* [PM-3313] Catch exception on AuthPendingRequest
* [PM-3313] Fix lock timeout action if user doesn't have a master password.
* code format
* [PM-3313] Null email in Approval Options screen (#2664)
* [PM-3313] Fix null email in approval options screen
* [PM-3320][PM-3321] Fix labels and UI tweaks (#2666)
* [PM-3320] Fix UI copy and remember me default ON.
* [PM-3321] Fix UI on Log in with device screen.
* [PM-3337] Fix admin request deny error (#2669)
* [PM-3342] Not you button logs user out. (#2672)
* [PM-3319] Check for admin request in Lock page (#2668)
* [PM-3319] Ignore admin auth request when choosing mp as decryption option.
* [PM-2289] Change header title based on auth request type (#2670)
* [PM-2289] Change header title based on auth request type
* [PM-3333] Check for purged admin auth requests (#2671)
* [PM-3333] Check for purged admin auth requests
Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
---------
Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
* [PM-3341] Vault Timeout Action not persisted correctly (#2673)
* [PM-3341] Fix timeout action change when navigating
* [PM-3357] Fix copy for Login Initiated (#2674)
* [PM-3362] Fix auth request approval (#2675)
* [PM-3362] Fix auth request approval
* [PM-3362] Add new exception type
* [PM-3102] Update Master password reprompt to be based on MP instead of Key Connector (#2653)
* PM-3102 Added check to see if a user has master password set replacing previous usage of key connector.
* PM-3102 Fix formatting
* [PM-2713] Final merge from Key Migration branch to TDE Feature branch (#2667)
* [PM-2713] add async to key connector service methods
* [PM-2713] rename ephemeral pin key
* add state for biometric key and accept UserKey instead of string for auto key
* Get UserKey from bio state on unlock
* PM-2713 Fix auto-migrating EncKeyEncrypted into MasterKey encrypted UserKey when requesting DecryptUserKeyWithMasterKeyAsync is called
* renaming bio key and fix build
* PM-3194 Fix biometrics button to be shown on upgrade when no UserKey is present yet
* revert removal of key connector service from auth service
* PM-2713 set user key when using KC
* clear enc user key after migration
* use is true for nullable bool
* PR feedback, refactor kc service
---------
Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
* Fix app fresh install user login with master password. (#2676)
* [PM-3303] Fix biometric login after key migration (#2679)
* [PM-3303] Add condition to biometric unlock
* [PM-3381] Fix TDE login 2FA flow (#2678)
* [PM-3381] Check for vault lock on 2FA screen
* [PM-3381] Move logic to ViewModel
* [PM-3381] Fix null vm error
* [PM-3379] Fix key rotation on trusted device. (#2680)
* [PM-3381] Update login flows (#2683)
* [PM-3381] Update login flows
* [PM-3381] Remove _authingWithSso parameter
* PM-3385 Fix MP reprompt item level when no MP hash is stored like logging in with TDE. Also refactor code to be more maintainable (#2687)
* PM-3386 Fix MP reprompt / OTP decision to be also based on the master key hash. (#2688)
* PM-3450 Fix has master password with mp key hash check (#2689)
* [PM-3394] Fix login with device for passwordless approvals (#2686)
* set activeUserId to null when logging in a new account
- Also stop the user key from being set in inactive accounts
* get token for login with device if approving device doesn't have master key
* add comment
* simplify logic
* check for route instead of using isAuthenticated
- we don't clear the user id when logging in new account
- this means we can't trust the state service, so we have to base our logic off the route in login with device
* use authenticated auth request for tde login with device
* [PM-3394] Add authingWithSso parameter to LoginPasswordlessRequestPage.
* pr feedback
* [PM-3394] Refactor condition
Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
---------
Co-authored-by: André Bispo <abispo@bitwarden.com>
Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
* [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>
* [PM-1029] Fix Async suffix in ApiService. Add UserKeyNullExceptions.
* [PM 3513] Fix passwordless 2fa login with device on mobile (#2700)
* [PM-3513] Fix 2FA for normal login with device with users without mp
* move _userKey
---------
Co-authored-by: André Bispo <abispo@bitwarden.com>
* clear encrypted pin on logout (#2699)
---------
Co-authored-by: André Bispo <abispo@bitwarden.com>
Co-authored-by: Jake Fink <jfink@bitwarden.com>
Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
(cherry picked from commit bfcfd367dd)
331 lines
15 KiB
C#
331 lines
15 KiB
C#
using System;
|
|
using System.Net;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Input;
|
|
using Bit.App.Abstractions;
|
|
using Bit.App.Resources;
|
|
using Bit.App.Utilities;
|
|
using Bit.Core.Abstractions;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Exceptions;
|
|
using Bit.Core.Models.Domain;
|
|
using Bit.Core.Services;
|
|
using Bit.Core.Utilities;
|
|
using Xamarin.CommunityToolkit.ObjectModel;
|
|
using Xamarin.Essentials;
|
|
|
|
namespace Bit.App.Pages
|
|
{
|
|
public class LoginSsoPageViewModel : BaseViewModel
|
|
{
|
|
private const string REDIRECT_URI = "bitwarden://sso-callback";
|
|
|
|
private readonly IDeviceActionService _deviceActionService;
|
|
private readonly IAuthService _authService;
|
|
private readonly ISyncService _syncService;
|
|
private readonly IApiService _apiService;
|
|
private readonly IPasswordGenerationService _passwordGenerationService;
|
|
private readonly ICryptoFunctionService _cryptoFunctionService;
|
|
private readonly IPlatformUtilsService _platformUtilsService;
|
|
private readonly IStateService _stateService;
|
|
private readonly ILogger _logger;
|
|
private readonly IOrganizationService _organizationService;
|
|
private readonly IDeviceTrustCryptoService _deviceTrustCryptoService;
|
|
private readonly ICryptoService _cryptoService;
|
|
|
|
private string _orgIdentifier;
|
|
|
|
public LoginSsoPageViewModel()
|
|
{
|
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
|
_authService = ServiceContainer.Resolve<IAuthService>("authService");
|
|
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
|
|
_apiService = ServiceContainer.Resolve<IApiService>("apiService");
|
|
_passwordGenerationService =
|
|
ServiceContainer.Resolve<IPasswordGenerationService>("passwordGenerationService");
|
|
_cryptoFunctionService = ServiceContainer.Resolve<ICryptoFunctionService>("cryptoFunctionService");
|
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
|
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
|
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
|
_organizationService = ServiceContainer.Resolve<IOrganizationService>();
|
|
_deviceTrustCryptoService = ServiceContainer.Resolve<IDeviceTrustCryptoService>();
|
|
_cryptoService = ServiceContainer.Resolve<ICryptoService>();
|
|
|
|
PageTitle = AppResources.Bitwarden;
|
|
LogInCommand = new AsyncCommand(LogInAsync, allowsMultipleExecutions: false);
|
|
}
|
|
|
|
public string OrgIdentifier
|
|
{
|
|
get => _orgIdentifier;
|
|
set => SetProperty(ref _orgIdentifier, value);
|
|
}
|
|
|
|
public ICommand LogInCommand { get; }
|
|
public Action StartTwoFactorAction { get; set; }
|
|
public Action StartSetPasswordAction { get; set; }
|
|
public Action SsoAuthSuccessAction { get; set; }
|
|
public Action StartDeviceApprovalOptionsAction { get; set; }
|
|
public Action CloseAction { get; set; }
|
|
public Action UpdateTempPasswordAction { get; set; }
|
|
|
|
public async Task InitAsync()
|
|
{
|
|
try
|
|
{
|
|
if (await TryClaimedDomainLogin())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(OrgIdentifier))
|
|
{
|
|
OrgIdentifier = await _stateService.GetRememberedOrgIdentifierAsync();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Exception(ex);
|
|
}
|
|
finally
|
|
{
|
|
await _deviceActionService.HideLoadingAsync();
|
|
}
|
|
}
|
|
|
|
public async Task LogInAsync()
|
|
{
|
|
try
|
|
{
|
|
if (Connectivity.NetworkAccess == NetworkAccess.None)
|
|
{
|
|
await _platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
|
|
AppResources.InternetConnectionRequiredTitle);
|
|
return;
|
|
}
|
|
if (string.IsNullOrWhiteSpace(OrgIdentifier))
|
|
{
|
|
await _platformUtilsService.ShowDialogAsync(
|
|
string.Format(AppResources.ValidationFieldRequired, AppResources.OrgIdentifier),
|
|
AppResources.AnErrorHasOccurred,
|
|
AppResources.Ok);
|
|
return;
|
|
}
|
|
|
|
await _deviceActionService.ShowLoadingAsync(AppResources.LoggingIn);
|
|
|
|
var response = await _apiService.PreValidateSsoAsync(OrgIdentifier);
|
|
|
|
if (string.IsNullOrWhiteSpace(response?.Token))
|
|
{
|
|
_logger.Error(response is null ? "Login SSO Error: response is null" : "Login SSO Error: response.Token is null or whitespace");
|
|
await _deviceActionService.HideLoadingAsync();
|
|
await _platformUtilsService.ShowDialogAsync(AppResources.LoginSsoError);
|
|
return;
|
|
}
|
|
|
|
var ssoToken = response.Token;
|
|
|
|
var passwordOptions = PasswordGenerationOptions.CreateDefault
|
|
.WithLength(64);
|
|
|
|
var codeVerifier = await _passwordGenerationService.GeneratePasswordAsync(passwordOptions);
|
|
var codeVerifierHash = await _cryptoFunctionService.HashAsync(codeVerifier, CryptoHashAlgorithm.Sha256);
|
|
var codeChallenge = CoreHelpers.Base64UrlEncode(codeVerifierHash);
|
|
|
|
var state = await _passwordGenerationService.GeneratePasswordAsync(passwordOptions);
|
|
|
|
var url = _apiService.IdentityBaseUrl + "/connect/authorize?" +
|
|
"client_id=" + _platformUtilsService.GetClientType().GetString() + "&" +
|
|
"redirect_uri=" + Uri.EscapeDataString(REDIRECT_URI) + "&" +
|
|
"response_type=code&scope=api%20offline_access&" +
|
|
"state=" + state + "&code_challenge=" + codeChallenge + "&" +
|
|
"code_challenge_method=S256&response_mode=query&" +
|
|
"domain_hint=" + Uri.EscapeDataString(OrgIdentifier) + "&" +
|
|
"ssoToken=" + Uri.EscapeDataString(ssoToken);
|
|
|
|
WebAuthenticatorResult authResult = null;
|
|
|
|
authResult = await WebAuthenticator.AuthenticateAsync(new Uri(url),
|
|
new Uri(REDIRECT_URI));
|
|
|
|
var code = GetResultCode(authResult, state);
|
|
if (!string.IsNullOrEmpty(code))
|
|
{
|
|
await LogIn(code, codeVerifier, OrgIdentifier);
|
|
}
|
|
else
|
|
{
|
|
await _deviceActionService.HideLoadingAsync();
|
|
await _platformUtilsService.ShowDialogAsync(AppResources.LoginSsoError,
|
|
AppResources.AnErrorHasOccurred);
|
|
}
|
|
}
|
|
catch (ApiException e)
|
|
{
|
|
_logger.Exception(e);
|
|
await _deviceActionService.HideLoadingAsync();
|
|
await _platformUtilsService.ShowDialogAsync(e?.Error?.GetSingleMessage() ?? AppResources.LoginSsoError,
|
|
AppResources.AnErrorHasOccurred);
|
|
}
|
|
catch (TaskCanceledException)
|
|
{
|
|
// user canceled
|
|
await _deviceActionService.HideLoadingAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Exception(ex);
|
|
await _deviceActionService.HideLoadingAsync();
|
|
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage, AppResources.AnErrorHasOccurred);
|
|
}
|
|
}
|
|
|
|
private string GetResultCode(WebAuthenticatorResult authResult, string state)
|
|
{
|
|
string code = null;
|
|
if (authResult != null)
|
|
{
|
|
authResult.Properties.TryGetValue("state", out var resultState);
|
|
if (resultState == state)
|
|
{
|
|
authResult.Properties.TryGetValue("code", out var resultCode);
|
|
code = resultCode;
|
|
}
|
|
}
|
|
return code;
|
|
}
|
|
|
|
private async Task LogIn(string code, string codeVerifier, string orgId)
|
|
{
|
|
try
|
|
{
|
|
var response = await _authService.LogInSsoAsync(code, codeVerifier, REDIRECT_URI, orgId);
|
|
var decryptOptions = await _stateService.GetAccountDecryptionOptions();
|
|
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
|
await _stateService.SetRememberedOrgIdentifierAsync(OrgIdentifier);
|
|
await _deviceActionService.HideLoadingAsync();
|
|
if (response.TwoFactor)
|
|
{
|
|
StartTwoFactorAction?.Invoke();
|
|
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 (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)
|
|
{
|
|
await _deviceTrustCryptoService.RemoveTrustedDeviceAsync();
|
|
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 (response.ForcePasswordReset)
|
|
{
|
|
UpdateTempPasswordAction?.Invoke();
|
|
return;
|
|
}
|
|
// Device is trusted and has keys, so we can decrypt
|
|
_syncService.FullSyncAsync(true).FireAndForget();
|
|
SsoAuthSuccessAction?.Invoke();
|
|
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();
|
|
SsoAuthSuccessAction?.Invoke();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
await _stateService.SetPendingAdminAuthRequestAsync(null);
|
|
StartDeviceApprovalOptionsAction?.Invoke();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StartDeviceApprovalOptionsAction?.Invoke();
|
|
}
|
|
return;
|
|
}
|
|
|
|
// In the standard, non TDE case, a user must set password if they don't
|
|
// have one and they aren't using key connector.
|
|
// Note: TDE & Key connector are mutually exclusive org config options.
|
|
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();
|
|
return;
|
|
}
|
|
|
|
_syncService.FullSyncAsync(true).FireAndForget();
|
|
SsoAuthSuccessAction?.Invoke();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
await _deviceActionService.HideLoadingAsync();
|
|
await _platformUtilsService.ShowDialogAsync(AppResources.LoginSsoError,
|
|
AppResources.AnErrorHasOccurred);
|
|
}
|
|
}
|
|
|
|
private async Task<bool> TryClaimedDomainLogin()
|
|
{
|
|
try
|
|
{
|
|
await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
|
|
var userEmail = await _stateService.GetPreLoginEmailAsync();
|
|
var claimedDomainOrgDetails = await _organizationService.GetClaimedOrganizationDomainAsync(userEmail);
|
|
await _deviceActionService.HideLoadingAsync();
|
|
|
|
if (claimedDomainOrgDetails == null || !claimedDomainOrgDetails.SsoAvailable)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(claimedDomainOrgDetails.OrganizationIdentifier))
|
|
{
|
|
await _platformUtilsService.ShowDialogAsync(AppResources.OrganizationSsoIdentifierRequired, AppResources.AnErrorHasOccurred);
|
|
return false;
|
|
}
|
|
|
|
OrgIdentifier = claimedDomainOrgDetails.OrganizationIdentifier;
|
|
await LogInAsync();
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HandleException(ex);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|