/// <summary> /// Async method for refreshing the token, persisting the data in the encrypted settings and returning the updated /// account /// with the new access token. /// </summary> /// <param name="account"></param> /// <returns>Boolean based on if the refresh auth token succeeded or not</returns> public static async Task <Account> RefreshAuthToken(Account account) { if (account != null) { try { AuthResponse response = await RefreshAuthTokenRequest(account.GetLoginOptions(), account.RefreshToken); account.AccessToken = response.AccessToken; AuthStorageHelper.GetAuthStorageHelper().PersistCredentials(account); } catch (WebException ex) { PlatformAdapter.SendToCustomLogger( "OAuth2.RefreshAuthToken - Exception occurred when refreshing token:", LoggingLevel.Critical); PlatformAdapter.SendToCustomLogger(ex, LoggingLevel.Critical); Debug.WriteLine("Error refreshing token"); throw new OAuthException(ex.Message, ex.Status); } catch (Exception ex) { PlatformAdapter.SendToCustomLogger( "OAuth2.RefreshAuthToken - Exception occurred when refreshing token:", LoggingLevel.Critical); PlatformAdapter.SendToCustomLogger(ex, LoggingLevel.Critical); Debug.WriteLine("Error refreshing token"); throw new OAuthException(ex.Message, ex.InnerException); } } return(account); }
private void CheckAccount(Account expectedAccount, bool exists) { AuthStorageHelper authStorageHelper = AuthStorageHelper.GetAuthStorageHelper(); TypeInfo auth = authStorageHelper.GetType().GetTypeInfo(); MethodInfo retrieve = auth.GetDeclaredMethod("RetrievePersistedCredentials"); var accounts = (Dictionary <string, Account>)retrieve.Invoke(authStorageHelper, null); if (!exists) { Assert.IsFalse(accounts.ContainsKey(expectedAccount.UserName), "Account " + expectedAccount.UserName + " should not have been found"); } else { Assert.IsTrue(accounts.ContainsKey(expectedAccount.UserName), "Account " + expectedAccount.UserName + " should exist"); Account account = accounts[expectedAccount.UserName]; Assert.AreEqual(expectedAccount.LoginUrl, account.LoginUrl); Assert.AreEqual(expectedAccount.ClientId, account.ClientId); Assert.AreEqual(expectedAccount.CallbackUrl, account.CallbackUrl); Assert.AreEqual(expectedAccount.Scopes.Length, account.Scopes.Length); Assert.AreEqual(expectedAccount.InstanceUrl, account.InstanceUrl); Assert.AreEqual(expectedAccount.AccessToken, expectedAccount.AccessToken); Assert.AreEqual(expectedAccount.RefreshToken, expectedAccount.RefreshToken); } }
public static async Task <bool> SwitchToAccount(Account account) { if (account != null && account.UserId != null) { AuthStorageHelper.GetAuthStorageHelper().PersistCredentials(account); RestClient client = SDKManager.GlobalClientManager.PeekRestClient(); if (client != null) { OAuth2.ClearCookies(account.GetLoginOptions()); IdentityResponse identity = await OAuth2.CallIdentityService(account.IdentityUrl, client); if (identity != null) { account.UserId = identity.UserId; account.UserName = identity.UserName; account.Policy = identity.MobilePolicy; AuthStorageHelper.GetAuthStorageHelper().PersistCredentials(account); } OAuth2.RefreshCookies(); PlatformAdapter.SendToCustomLogger("AccountManager.SwitchToAccount - done, result = true", LoggingLevel.Verbose); return(true); } } PlatformAdapter.SendToCustomLogger("AccountManager.SwitchToAccount - done, result = false", LoggingLevel.Verbose); return(false); }
/// <summary> /// This will return true if there is a master pincode set. /// </summary> /// <returns></returns> public static bool IsPincodeSet() { bool result = AuthStorageHelper.GetAuthStorageHelper().RetrievePincode() != null; PlatformAdapter.SendToCustomLogger(string.Format("AuthStorageHelper.IsPincodeSet - result = {0}", result), LoggingLevel.Verbose); return(result); }
/// <summary> /// This will wipe out the pincode and associated data. /// </summary> public static void WipePincode() { AuthStorageHelper auth = AuthStorageHelper.GetAuthStorageHelper(); auth.DeletePincode(); auth.DeleteData(PinBackgroundedTimeKey); auth.DeleteData(PincodeRequired); PlatformAdapter.SendToCustomLogger("PincodeManager.WipePincode - Pincode wiped", LoggingLevel.Verbose); }
public static string RetrievePinCodeHash() { var policy = AuthStorageHelper.GetMobilePolicy(); if (policy?.PincodeHash != null) { return(policy.PincodeHash); } return(string.Empty); }
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) { if (e != null && Options != null && PincodeOptions.PincodeScreen.Locked.Equals(Options.Screen) && AuthStorageHelper.IsPincodeRequired()) { e.Cancel = true; } base.OnNavigatingFrom(e); }
/// <summary> /// This method will launch the pincode screen if the policy requires it. /// If determined that no pincode screen is required, the flag requiring the pincode will be cleared. /// </summary> public static async void LaunchPincodeScreen() { var frame = Window.Current.Content as Frame; if (frame != null && typeof(PincodeDialog) != frame.SourcePageType) { await frame.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { SDKServiceLocator.Get <ILoggingService>().Log(" Launching Pincode Screen", LoggingLevel.Information); Account account = AccountManager.GetAccount(); if (account != null) { PincodeOptions options = null; bool required = AuthStorageHelper.IsPincodeRequired(); if (account.Policy != null && !IsPincodeSet()) { options = new PincodeOptions(PincodeOptions.PincodeScreen.Create, account, ""); } else if (required) { MobilePolicy policy = AuthStorageHelper.GetMobilePolicy(); if (account.Policy != null) { if (policy.ScreenLockTimeout < account.Policy.ScreenLockTimeout) { policy.ScreenLockTimeout = account.Policy.ScreenLockTimeout; AuthStorageHelper.GetAuthStorageHelper().PersistPincode(policy); } if (policy.PinLength < account.Policy.PinLength) { options = new PincodeOptions(PincodeOptions.PincodeScreen.Create, account, ""); } else { options = new PincodeOptions(PincodeOptions.PincodeScreen.Locked, account, ""); } } else { options = new PincodeOptions(PincodeOptions.PincodeScreen.Locked, account, ""); } } if (options != null) { // As per MSDN documentation (https://msdn.microsoft.com/en-us/library/windows/apps/hh702394.aspx) // the second param of Frame.Navigate must be a basic type otherwise Suspension manager will crash // when serializing frame's state. So we serialize custom object using Json and pass that as the // second param to avoid this crash. frame.Navigate(typeof(PincodeDialog), PincodeOptions.ToJson(options)); } } }); } }
public static void SavePinTimer() { MobilePolicy policy = GetMobilePolicy(); Account account = AccountManager.GetAccount(); if (account != null && policy != null && policy.ScreenLockTimeout > 0) { PlatformAdapter.SendToCustomLogger("AuthStorageHelper.SavePinTimer - saving pin timer", LoggingLevel.Verbose); AuthStorageHelper.GetAuthStorageHelper() .PersistData(true, PinBackgroundedTimeKey, DateTime.Now.ToUniversalTime().ToString()); } }
/// <summary> /// Returns the global mobile policy stored. /// </summary> /// <returns></returns> public static MobilePolicy GetMobilePolicy() { string retrieved = AuthStorageHelper.GetAuthStorageHelper().RetrievePincode(); if (retrieved != null) { PlatformAdapter.SendToCustomLogger("AuthStorageHelper.GetMobilePolicy - returning retrieved policy", LoggingLevel.Verbose); return(JsonConvert.DeserializeObject <MobilePolicy>(retrieved)); } PlatformAdapter.SendToCustomLogger("AuthStorageHelper.GetMobilePolicy - No policy found", LoggingLevel.Verbose); return(null); }
public void TestPersistRetrieveDeleteEncryptionSettings() { AuthStorageHelper authStorageHelper = AuthStorageHelper.GetAuthStorageHelper(); TypeInfo auth = authStorageHelper.GetType().GetTypeInfo(); MethodInfo persist = auth.GetDeclaredMethod("PersistEncryptionSettings"); MethodInfo delete = auth.GetDeclaredMethod("DeleteEncryptionSettings"); persist.Invoke(authStorageHelper, new object[] { Password, Salt }); CheckEncryptionSettings(true); delete.Invoke(authStorageHelper, null); CheckEncryptionSettings(false); }
/// <summary> /// Delete Account (log out) for currently authenticated user /// </summary> public static void DeleteAccount() { var account = GetAccount(); if (account == null) { return; } AuthStorageHelper.DeletePersistedAccount(account.UserName, account.UserId); LoggedInAccount = null; }
/// <summary> /// Stores the pincode and associated mobile policy information including pin length and screen lock timeout. /// </summary> /// <param name="policy"></param> /// <param name="pincode"></param> public static void StorePincode(MobilePolicy policy, string pincode) { string hashed = GenerateEncryptedPincode(pincode); var mobilePolicy = new MobilePolicy { ScreenLockTimeout = policy.ScreenLockTimeout, PinLength = policy.PinLength, PincodeHash = Encryptor.Encrypt(hashed, pincode) }; AuthStorageHelper.GetAuthStorageHelper().PersistPincode(mobilePolicy); PlatformAdapter.SendToCustomLogger("AuthStorageHelper.StorePincode - Pincode stored", LoggingLevel.Verbose); }
/// <summary> /// Create and persist Account for newly authenticated user /// </summary> /// <param name="loginOptions"></param> /// <param name="authResponse"></param> /// <param name="cancellationToken"></param> public static async Task <Account> CreateNewAccount(LoginOptions loginOptions, AuthResponse authResponse, CancellationToken cancellationToken = default(CancellationToken)) { LoggingService.Log("Create account object", LoggingLevel.Verbose); var account = new Account( loginOptions.LoginUrl, loginOptions.ClientId, loginOptions.CallbackUrl, loginOptions.Scopes, authResponse.InstanceUrl, authResponse.IdentityUrl, authResponse.AccessToken, authResponse.RefreshToken) { CommunityId = authResponse.CommunityId, CommunityUrl = authResponse.CommunityUrl }; var cm = new ClientManager(); cm.PeekRestClient(); IdentityResponse identity = null; try { identity = await OAuth2.CallIdentityServiceAsync(authResponse.IdentityUrl, authResponse.AccessToken, cancellationToken); } catch (JsonException ex) { LoggingService.Log(ex, LoggingLevel.Critical, "Exception occurred when retrieving account identity"); Debug.WriteLine("Error retrieving account identity"); } if (identity != null) { account.UserId = identity.UserId; account.UserName = identity.UserName; account.Policy = identity.MobilePolicy; account.OrganizationId = identity.OrganizationId; await AuthStorageHelper.PersistCurrentAccountAsync(account); LoggedInAccount = account; } LoggingService.Log("Finished creating account", LoggingLevel.Verbose); return(account); }
/// <summary> /// This should be called when login is complete. A new account is created /// in the AccountManager and the pincode screen is shown if needeed /// </summary> /// <param name="loginOptions"></param> /// <param name="authResponse"></param> public async Task OnLoginCompleteAsync(LoginOptions loginOptions, AuthResponse authResponse) { var frame = Window.Current.Content as Frame; var account = await AccountManager.CreateNewAccount(loginOptions, authResponse); if (account.Policy != null && (!PincodeManager.IsPincodeSet() || AuthStorageHelper.IsPincodeRequired())) { PincodeManager.LaunchPincodeScreen(); } else { SDKServiceLocator.Get <ILoggingService>().Log($"Navigating to {SDKManager.RootApplicationPage}", LoggingLevel.Information); frame?.Navigate(SDKManager.RootApplicationPage); } }
public void TestPersistRetrieveDeleteCredentials() { Account account = new Account("loginUrl", "clientId", "callbackUrl", new string[] { "scopeA", "scopeB" }, "instanceUrl", "identityUrl", "accessToken", "refreshToken"); account.UserId = "userId"; account.UserName = "******"; AuthStorageHelper authStorageHelper = new AuthStorageHelper(); CheckAccount(account, false); TypeInfo auth = authStorageHelper.GetType().GetTypeInfo(); MethodInfo persist = auth.GetDeclaredMethod("PersistCredentials"); MethodInfo delete = auth.GetDeclaredMethods("DeletePersistedCredentials").First(method => method.GetParameters().Count() == 1); persist.Invoke(authStorageHelper, new object[] { account }); CheckAccount(account, true); delete.Invoke(authStorageHelper, new object[] { account.UserId }); CheckAccount(account, false); }
/// <summary> /// Persist oauth credentials via the AccountManager /// </summary> /// <param name="loginOptions"></param> /// <param name="authResponse"></param> public async void EndLoginFlow(LoginOptions loginOptions, AuthResponse authResponse) { var frame = Window.Current.Content as Frame; Account account = await AccountManager.CreateNewAccount(loginOptions, authResponse); if (account.Policy != null && (!PincodeManager.IsPincodeSet() || AuthStorageHelper.IsPincodeRequired())) { PincodeManager.LaunchPincodeScreen(); } else { PlatformAdapter.SendToCustomLogger(string.Format("AuthHelper.EndLoginFlow - Navigating to {0}", SDKManager.RootApplicationPage), LoggingLevel.Information); frame.Navigate(SDKManager.RootApplicationPage); } }
public static void StartIdleTimer() { if (IsPincodeSet()) { var policy = AuthStorageHelper.GetMobilePolicy(); if (policy != null) { IdleTimer.Interval = TimeSpan.FromMinutes(policy.ScreenLockTimeout); if (IdleTimer.IsEnabled) { IdleTimer.Stop(); } SavePinTimer(); IdleTimer.Start(); } } }
public static void TriggerBackgroundedPinTimer() { Account account = AccountManager.GetAccount(); MobilePolicy policy = AuthStorageHelper.GetMobilePolicy(); bool required = AuthStorageHelper.IsPincodeRequired(); if (account != null) { if (required || (policy == null && account.Policy != null)) { LaunchPincodeScreen(); } } else if (!required) { AuthStorageHelper.ClearPinTimer(); } }
private void CheckEncryptionSettings(bool exists) { AuthStorageHelper authStorageHelper = AuthStorageHelper.GetAuthStorageHelper(); TypeInfo auth = authStorageHelper.GetType().GetTypeInfo(); MethodInfo tryRetrieve = auth.GetDeclaredMethod("TryRetrieveEncryptionSettings"); var parameters = new object[] { null, null }; var success = (bool)tryRetrieve.Invoke(authStorageHelper, parameters); if (!exists) { Assert.IsFalse(success, "Encryption settings should not exist"); } else { Assert.IsTrue(success, "Encryption settings should exist"); Assert.AreEqual(Password, parameters[0]); Assert.AreEqual(Salt, parameters[1]); } }
private void ConfirmClicked(object sender, KeyRoutedEventArgs e) { if (e.Key != VirtualKey.Accept && e.Key != VirtualKey.Enter) { return; } e.Handled = true; if (Passcode.Password.Equals(Options.Passcode)) { LoggingService.Log($"Pincode matched, going to {SDKManager.RootApplicationPage}", LoggingLevel.Verbose); AuthStorageHelper.StorePincode(Options.Policy, Options.Passcode); PincodeManager.Unlock(); Frame.Navigate(SDKManager.RootApplicationPage); } else { DisplayErrorFlyout(LocalizedStrings.GetString("passcode_must_match")); } }
public static async Task <bool> SwitchToAccountAsync(Account newAccount, CancellationToken cancellationToken = default(CancellationToken)) { var oldAccount = LoggedInAccount; if (newAccount?.UserId != null) { // save current user pin timer AuthStorageHelper.SavePinTimer(); await AuthStorageHelper.PersistCurrentAccountAsync(newAccount); var client = SDKManager.GlobalClientManager.PeekRestClient(); if (client != null) { await AuthStorageHelper.ClearCookiesAsync(newAccount.GetLoginOptions()); var identity = await OAuth2.CallIdentityServiceAsync(newAccount.IdentityUrl, client, cancellationToken); if (identity != null) { newAccount.UserId = identity.UserId; newAccount.UserName = identity.UserName; newAccount.Policy = identity.MobilePolicy; await AuthStorageHelper.PersistCurrentAccountAsync(newAccount); } AuthStorageHelper.RefreshCookies(); LoggingService.Log("switched accounts, result = true", LoggingLevel.Verbose); return(true); } // log new user in LoggedInAccount = newAccount; RaiseAuthenticatedAccountChangedEvent(oldAccount, newAccount); } LoggingService.Log("switched accounts, result = false", LoggingLevel.Verbose); return(false); }
/// <summary> /// Create and persist Account for newly authenticated user /// </summary> /// <param name="loginOptions"></param> /// <param name="authResponse"></param> public static async Task <Account> CreateNewAccount(LoginOptions loginOptions, AuthResponse authResponse) { PlatformAdapter.SendToCustomLogger("AccountManager.CreateNewAccount - create account object", LoggingLevel.Verbose); var account = new Account(loginOptions.LoginUrl, loginOptions.ClientId, loginOptions.CallbackUrl, loginOptions.Scopes, authResponse.InstanceUrl, authResponse.IdentityUrl, authResponse.AccessToken, authResponse.RefreshToken); account.CommunityId = authResponse.CommunityId; account.CommunityUrl = authResponse.CommunityUrl; IdentityResponse identity = null; try { var cm = new ClientManager(); cm.PeekRestClient(); identity = await OAuth2.CallIdentityService(authResponse.IdentityUrl, authResponse.AccessToken); } catch (JsonException ex) { PlatformAdapter.SendToCustomLogger( "AccountManager.CreateNewAccount - Exception occurred when retrieving account identity:", LoggingLevel.Critical); PlatformAdapter.SendToCustomLogger(ex, LoggingLevel.Critical); Debug.WriteLine("Error retrieving account identity"); } if (identity != null) { account.UserId = identity.UserId; account.UserName = identity.UserName; account.Policy = identity.MobilePolicy; AuthStorageHelper.GetAuthStorageHelper().PersistCredentials(account); } PlatformAdapter.SendToCustomLogger("AccountManager.CreateNewAccount - done", LoggingLevel.Verbose); return(account); }
/// <summary> /// Validate the given pincode against the stored pincode. /// </summary> /// <param name="pincode">Pincode to validate</param> /// <returns>True if pincode matches</returns> public static bool ValidatePincode(string pincode) { string compare = GenerateEncryptedPincode(pincode); try { string retrieved = AuthStorageHelper.GetAuthStorageHelper().RetrievePincode(); var policy = JsonConvert.DeserializeObject <MobilePolicy>(retrieved); bool result = compare.Equals(Encryptor.Decrypt(policy.PincodeHash, pincode)); PlatformAdapter.SendToCustomLogger(string.Format("AuthStorageHelper.ValidatePincode - result = {0}", result), LoggingLevel.Verbose); return(result); } catch (Exception ex) { PlatformAdapter.SendToCustomLogger("AuthStorageHelper.ValidatePincode - Exception occurred when validating pincode:", LoggingLevel.Critical); PlatformAdapter.SendToCustomLogger(ex, LoggingLevel.Critical); Debug.WriteLine("Error validating pincode"); } return(false); }
/// <summary> /// This will return true if a pincode is required before the app can be accessed. /// </summary> /// <returns></returns> public static bool IsPincodeRequired() { AuthStorageHelper auth = GetAuthStorageHelper(); // a flag is set if the timer was exceeded at some point. Automatically return true if the flag is set. bool required = auth.RetrieveData(PincodeRequired) != null; if (required) { PlatformAdapter.SendToCustomLogger("AuthStorageHelper.IsPincodeRequired - Pincode is required", LoggingLevel.Verbose); return(true); } if (IsPincodeSet()) { MobilePolicy policy = GetMobilePolicy(); if (policy != null) { string time = auth.RetrieveData(PinBackgroundedTimeKey); if (time != null) { DateTime previous = DateTime.Parse(time); DateTime current = DateTime.Now.ToUniversalTime(); TimeSpan diff = current.Subtract(previous); if (diff.Minutes >= policy.ScreenLockTimeout) { // flag that requires pincode to be entered in the future. Until the flag is deleted a pincode will be required. auth.PersistData(true, PincodeRequired, time); PlatformAdapter.SendToCustomLogger("AuthStorageHelper.IsPincodeRequired - Pincode is required", LoggingLevel.Verbose); return(true); } } } } // We aren't requiring pincode, so remove the flag. auth.DeleteData(PincodeRequired); PlatformAdapter.SendToCustomLogger("AuthStorageHelper.IsPincodeRequired - Pincode is not required", LoggingLevel.Verbose); return(false); }
private async void LockedClick(object sender, KeyRoutedEventArgs e) { if (e.Key != VirtualKey.Accept && e.Key != VirtualKey.Enter) { return; } e.Handled = true; Account account = AccountManager.GetAccount(); if (account == null) { await SDKServiceLocator.Get <IAuthHelper>().StartLoginFlowAsync(); } else if (AuthStorageHelper.ValidatePincode(Passcode.Password)) { PincodeManager.Unlock(); if (Frame.CanGoBack) { Frame.GoBack(); } else { Frame.Navigate(SDKManager.RootApplicationPage); } } else { if (RetryCounter <= 1) { await SDKManager.GlobalClientManager.Logout(); } RetryCounter--; ContentFooter.Text = String.Format(LocalizedStrings.GetString("passcode_incorrect"), RetryCounter); ContentFooter.Visibility = Visibility.Visible; } }
public static AuthStorageHelper GetAuthStorageHelper() { return _singletonAuthStorageHelper ?? (_singletonAuthStorageHelper = new AuthStorageHelper()); }
public void TestGetAuthStorageHelper() { AuthStorageHelper authStorageHelper = new AuthStorageHelper(); Assert.IsNotNull(authStorageHelper); }
public static void SavePinTimer() { AuthStorageHelper.SavePinTimer(); }
/// <summary> /// Clear the pincode flag. /// </summary> internal static void Unlock() { AuthStorageHelper.Unlock(); }
/// <summary> /// This will return true if there is a master pincode set. /// </summary> /// <returns></returns> public static bool IsPincodeSet() { return(AuthStorageHelper.IsPincodeSet()); }
private void CheckAccount(Account expectedAccount, bool exists) { AuthStorageHelper authStorageHelper = new AuthStorageHelper(); TypeInfo auth = authStorageHelper.GetType().GetTypeInfo(); MethodInfo retrieve = auth.GetDeclaredMethod("RetrievePersistedCredentials"); var accounts = (Dictionary<string, Account>) retrieve.Invoke(authStorageHelper, null); if (!exists) { Assert.IsFalse(accounts.ContainsKey(expectedAccount.UserId), "Account " + expectedAccount.UserId + " should not have been found"); } else { Assert.IsTrue(accounts.ContainsKey(expectedAccount.UserId), "Account " + expectedAccount.UserId + " should exist"); Account account = accounts[expectedAccount.UserId]; Assert.AreEqual(expectedAccount.LoginUrl, account.LoginUrl); Assert.AreEqual(expectedAccount.ClientId, account.ClientId); Assert.AreEqual(expectedAccount.CallbackUrl, account.CallbackUrl); Assert.AreEqual(expectedAccount.Scopes.Length, account.Scopes.Length); Assert.AreEqual(expectedAccount.InstanceUrl, account.InstanceUrl); Assert.AreEqual(expectedAccount.AccessToken, expectedAccount.AccessToken); Assert.AreEqual(expectedAccount.RefreshToken, expectedAccount.RefreshToken); } }
private AccountManager() { InternalAuthStorage = new AuthStorageHelper(); }
public Task PersistCurrentAccountAsync(Account account) { AuthStorageHelper.GetAuthStorageHelper().PersistCurrentCredentials(account); return(Task.FromResult(0)); }