public static void ClassSetup(TestContext context) { SFApplicationHelper.RegisterServices(); SDKServiceLocator.RegisterService <ILoggingService, Hybrid.Logging.Logger>(); Store = SmartStore.GetGlobalSmartStore(); SetupData(); }
public static void RegisterServices() { SDKServiceLocator.RegisterService <ISFApplicationHelper, SFApplicationHelper>(); SDKServiceLocator.RegisterService <IAuthHelper, AuthHelper>(); SDKServiceLocator.RegisterService <IEncryptionService, Encryptor>(); SDKServiceLocator.RegisterService <IApplicationInformationService, ApplicationService>(); }
public static void TestSetup(TestContext context) { SFApplicationHelper.RegisterServices(); SDKServiceLocator.RegisterService <ILoggingService, Hybrid.Logging.Logger>(); Store = SmartStore.GetGlobalSmartStore(); Store.ResetDatabase(); Store.RegisterSoup(TEST_SOUP, new[] { new IndexSpec("key", SmartStoreType.SmartString) }); }
protected override Task InitializeConfig() { SDKServiceLocator.RegisterService <IEncryptionService, Encryptor>(); Encryptor.init(new EncryptionSettings(new HmacSHA256KeyGenerator(HashAlgorithmNames.Sha256))); var config = SDKManager.InitializeConfigAsync <Config>().Result; return(config.SaveConfigAsync()); }
private async Task CheckIfLoginNeededAsync() { Account account = AccountManager.GetAccount(); if (account == null) { SDKServiceLocator.Get <ILoggingService>().Log("Account object is null, calling StartLoginFlowAsync", LoggingLevel.Verbose); await SDKServiceLocator.Get <IAuthHelper>().StartLoginFlowAsync(); } }
/// <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)); } } }); } }
/// <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> RefreshAuthTokenAsync(Account account) { LoggingService.Log("Atempting to refresh auth token", LoggingLevel.Verbose); if (account == null) { return(null); } try { var loginOptions = account.GetLoginOptions(); // args var argsStr = string.Format(OauthRefreshQueryString, loginOptions.ClientId, account.RefreshToken); // Refresh url var refreshUrl = loginOptions.LoginUrl + OauthRefreshPath; // Post var call = HttpCall.CreatePost(refreshUrl, argsStr); var response = await call.ExecuteAndDeserializeAsync <AuthResponse>(); account.AccessToken = response.AccessToken; account.IdentityUrl = response.IdentityUrl; await SDKServiceLocator.Get <IAuthHelper>().PersistCurrentAccountAsync(account); } catch (DeviceOfflineException ex) { LoggingService.Log("Failed to refresh the token because we were offline", LoggingLevel.Warning); LoggingService.Log(ex, LoggingLevel.Warning); throw; } catch (WebException ex) { LoggingService.Log("Exception occurred when refreshing token:", LoggingLevel.Critical); LoggingService.Log(ex, LoggingLevel.Critical); Debug.WriteLine("Error refreshing token"); throw new OAuthException(ex.Message, ex); } catch (Exception ex) { LoggingService.Log("Exception occurred when refreshing token:", LoggingLevel.Critical); LoggingService.Log(ex, LoggingLevel.Critical); Debug.WriteLine("Error refreshing token"); throw new OAuthException(ex.Message, ex); } return(account); }
private static void RegisterServices() { // setup logger SDKServiceLocator.RegisterService <ILoggingService, Logger>(); // log registering services LoggingService.Log("Registering Services", LoggingLevel.Information); // register remaining services SDKServiceLocator.RegisterService <IAuthHelper, AuthHelper>(); SDKServiceLocator.RegisterService <IEncryptionService, Encryptor>(); SDKServiceLocator.RegisterService <IApplicationInformationService, ApplicationService>(); }
private async void RefreshToken(object sender, object e) { try { //Assign this to a var as ref requires it. var account = AccountManager.GetAccount(); await OAuth2.RefreshAuthTokenAsync(account); SDKServiceLocator.Get <IAuthHelper>().RefreshCookies(); } catch (OAuthException ex) { LoggingService.Log(ex, LoggingLevel.Critical, "Error occurred when refreshing token"); } }
/// <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 Dispose() { if (_httpClient == null) { return; } try { _httpClient.Dispose(); } catch (Exception) { SDKServiceLocator.Get <ILoggingService>().Log("Error occurred while disposing", LoggingLevel.Warning); } }
/// <summary> /// Returns a RestClient if user is already authenticated or otherwise kicks off a login flow /// </summary> /// <returns></returns> public IRestClient GetRestClient() { var restClient = PeekRestClient(); if (restClient == null) { try { AuthHelper.StartLoginFlowAsync(); } catch (InvalidOperationException) { SDKServiceLocator.Get <ILoggingService>().Log("Platform doesn't support native login flow", LoggingLevel.Information); } } return(restClient); }
protected SalesforceApplication() { SFApplicationHelper.RegisterServices(); SDKServiceLocator.RegisterService <ILoggingService, Logger>(); Suspending += OnSuspending; //do upgrade on stored config, account and pincode UpgradeConfigAsync().Wait(); SDKUpgradeManager.GetInstance().UpgradeAsync().Wait(); InitializeConfig(); SDKManager.CreateClientManager(false); SDKManager.RootApplicationPage = SetRootApplicationPage(); TokenRefresher = new DispatcherTimer { Interval = TimeSpan.FromMinutes(TokenRefreshInterval) }; TokenRefresher.Tick += RefreshToken; AppHelper.Initialize(); }
public static async Task TestSetup(TestContext context) { SFApplicationHelper.RegisterServices(); SDKServiceLocator.RegisterService <ILoggingService, Hybrid.Logging.Logger>(); var settings = new EncryptionSettings(new HmacSHA256KeyGenerator(HashAlgorithmNames.Sha256)); Encryptor.init(settings); var options = new LoginOptions(TestCredentials.LoginUrl, TestCredentials.ClientId, TestCallbackUrl, "mobile", TestScopes); var response = new AuthResponse { RefreshToken = TestCredentials.RefreshToken, AccessToken = TestAuthToken, InstanceUrl = TestCredentials.InstanceUrl, IdentityUrl = TestCredentials.IdentityUrl, Scopes = TestScopes, }; Account account = await AccountManager.CreateNewAccount(options, response); account.UserId = TestCredentials.UserId; account.UserName = TestCredentials.Username; await OAuth2.RefreshAuthTokenAsync(account); _smartStore = SmartStore.GetSmartStore(); _smartStore.ResetDatabase(); _syncManager = SyncManager.GetInstance(); _restClient = new RestClient(account.InstanceUrl, account.AccessToken, async(cancellationToken) => { account = AccountManager.GetAccount(); account = await OAuth2.RefreshAuthTokenAsync(account); return(account.AccessToken); } ); CreateAccountsSoup(); _idToNames = await CreateTestAccountsOnServer(CountTestAccounts); }
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; } }
/// <summary> /// Executes the HttpCall. This will generate the headers, create the request and populate the HttpCall properties with /// relevant data. /// The HttpCall may only be called once; further attempts to execute the same call will throw an /// InvalidOperationException. /// </summary> /// <param name="cancellationToken"></param> /// <returns>HttpCall with populated data</returns> public async Task <HttpCall> ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (Executed) { throw new InvalidOperationException("A HttpCall can only be executed once"); } var req = new HttpRequestMessage(_method, new Uri(_url)); // Setting header if (_headers != null) { if (_headers.Authorization != null) { req.Headers.Authorization = _headers.Authorization; } foreach (var item in _headers.Headers) { req.Headers.Add(item.Key, item.Value); } } // if the user agent has not yet been set, set it; we want to make sure this only really happens once since it requires an action that goes to the core thread. if (String.IsNullOrWhiteSpace(UserAgentHeader)) { UserAgentHeader = await SDKServiceLocator.Get <IApplicationInformationService>().GenerateUserAgentHeaderAsync(false, String.Empty); } req.Headers.UserAgent.TryParseAdd(UserAgentHeader); if (!String.IsNullOrWhiteSpace(_requestBody)) { switch (_contentType) { case ContentTypeValues.FormUrlEncoded: req.Content = new FormUrlEncodedContent(_requestBody.ParseQueryString()); break; case ContentTypeValues.Gzip: req.Content = await CompressAsync(new StringContent(_requestBody)); break; default: req.Content = new StringContent(_requestBody); req.Content.Headers.ContentType = new MediaTypeHeaderValue(_contentType.MimeType()); break; } } HttpResponseMessage message; try { message = await _httpClient.SendAsync(req, cancellationToken); } catch (HttpRequestException ex) { _httpCallErrorException = new DeviceOfflineException("Request failed to send, most likely because we were offline", ex); return(this); } catch (WebException ex) { _httpCallErrorException = new DeviceOfflineException("Request failed to send, most likely because we were offline", ex); return(this); } // If the result is null then it might be because the http call was canceled. // HttpClient has a bug where it doesn't throw when a cancellation is requested, // it just returns null immediately (however the cancellation token does get set // to canceled). More context on that bug at: // http://stackoverflow.com/questions/29319086/cancelling-an-httpclient-request-why-is-taskcanceledexception-cancellationtoke // The following if block will throw an OperationCanceledException (which is the // desired behavior for when a Task gets canceled) if a cancel was requested // and works around the HttpClient bug. if (message == null) { cancellationToken.ThrowIfCancellationRequested(); } await HandleMessageResponseAsync(message); return(this); }
public static void SetupClass(TestContext context) { SFApplicationHelper.RegisterServices(); SDKServiceLocator.RegisterService <ILoggingService, Hybrid.Logging.Logger>(); }
private async void DoAuthFlow(LoginOptions loginOptions) { loginOptions.DisplayType = LoginOptions.DefaultStoreDisplayType; var loginUri = new Uri(OAuth2.ComputeAuthorizationUrl(loginOptions)); var callbackUri = new Uri(loginOptions.CallbackUrl); await SDKServiceLocator.Get <IAuthHelper>().ClearCookiesAsync(loginOptions); WebAuthenticationResult webAuthenticationResult = null; var hasWebAuthErrors = false; try { LoggingService.Log("Launching web authentication broker", LoggingLevel.Verbose); webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, loginUri, callbackUri); } // If a bad URI was passed in the user is shown an error message by the WebAuthenticationBroken, when user // taps back arrow we are then thrown a FileNotFoundException, but since user already saw error message we // should just swallow that exception catch (FileNotFoundException) { SetupAccountPage(); return; } catch (Exception ex) { LoggingService.Log("Exception occurred during login flow", LoggingLevel.Critical); LoggingService.Log(ex, LoggingLevel.Critical); hasWebAuthErrors = true; } if (hasWebAuthErrors) { await DisplayErrorDialogAsync(LocalizedStrings.GetString("generic_error")); SetupAccountPage(); return; } if (webAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success) { var responseUri = new Uri(webAuthenticationResult.ResponseData); if (!String.IsNullOrWhiteSpace(responseUri.Query) && responseUri.Query.IndexOf("error", StringComparison.CurrentCultureIgnoreCase) >= 0) { await DisplayErrorDialogAsync(LocalizedStrings.GetString("generic_authentication_error")); SetupAccountPage(); } else { AuthResponse authResponse = OAuth2.ParseFragment(responseUri.Fragment.Substring(1)); await SDKServiceLocator.Get <IAuthHelper>().OnLoginCompleteAsync(loginOptions, authResponse); } } else if (webAuthenticationResult.ResponseStatus == WebAuthenticationStatus.UserCancel) { SetupAccountPage(); } else { await DisplayErrorDialogAsync(LocalizedStrings.GetString("generic_error")); SetupAccountPage(); } }
private HybridAccountManager() { RegisterServices(); SDKServiceLocator.Get <IApplicationInformationService>().GenerateUserAgentHeaderAsync(true, String.Empty); }
public void SetupTest() { SFApplicationHelper.RegisterServices(); SDKServiceLocator.RegisterService <ILoggingService, Hybrid.Logging.Logger>(); }
/// <summary> /// Executes the HttpCall. This will generate the headers, create the request and populate the HttpCall properties with /// relevant data. /// The HttpCall may only be called once; further attempts to execute the same call will throw an /// InvalidOperationException. /// </summary> /// <returns>HttpCall with populated data</returns> public async Task <HttpCall> ExecuteAsync() { if (Executed) { throw new InvalidOperationException("A HttpCall can only be executed once"); } var req = new HttpRequestMessage(_method, new Uri(_url)); // Setting header if (_headers != null) { if (_headers.Authorization != null) { req.Headers.Authorization = _headers.Authorization; } foreach (var item in _headers.Headers) { req.Headers.Add(item.Key, item.Value); } } // if the user agent has not yet been set, set it; we want to make sure this only really happens once since it requires an action that goes to the core thread. if (String.IsNullOrWhiteSpace(UserAgentHeader)) { UserAgentHeader = await SDKServiceLocator.Get <IApplicationInformationService>().GenerateUserAgentHeaderAsync(false, String.Empty); } req.Headers.UserAgent.TryParseAdd(UserAgentHeader); if (!String.IsNullOrWhiteSpace(_requestBody)) { switch (_contentType) { case ContentTypeValues.FormUrlEncoded: req.Content = new FormUrlEncodedContent(_requestBody.ParseQueryString()); break; default: req.Content = new StringContent(_requestBody); req.Content.Headers.ContentType = new MediaTypeHeaderValue(_contentType.MimeType()); break; } } HttpResponseMessage message; try { message = await _httpClient.SendAsync(req); } catch (HttpRequestException ex) { _httpCallErrorException = new DeviceOfflineException("Request failed to send, most likely because we were offline", ex); return(this); } catch (WebException ex) { _httpCallErrorException = new DeviceOfflineException("Request failed to send, most likely because we were offline", ex); return(this); } await HandleMessageResponseAsync(message); return(this); }