/// <summary> /// Salva su file le credenziali di accesso al canale /// </summary> /// <param name="playerID">Id del dispositivo</param> /// <param name="token">Token di accesso o id del canale</param> /// <returns></returns> private async Task SaveNotificationCredentials(string playerID, string token) { try { StorageFolder localFolder = ApplicationData.Current.LocalFolder; StorageFile pushNotificationFile = await localFolder.CreateFileAsync("push.notification", CreationCollisionOption.ReplaceExisting); if (pushNotificationFile != null) { JObject jObject = new JObject { { "token", new JValue(token) }, { "playerid", new JValue(playerID) } }; EncDecHelper encDecHelper = new EncDecHelper { Password = GetDevicePwd() }; string encryptedContent = encDecHelper.AESEncrypt(jObject.ToString()); await FileIO.WriteTextAsync(pushNotificationFile, encryptedContent, Windows.Storage.Streams.UnicodeEncoding.Utf8); } } catch (Exception ex) { Debug.WriteLine("Errore di scrittura del file di configurazione delle notifiche push. Exception: " + ex.Message); } }
/// <summary> /// Ricostruisce le informazioni di accesso al Cloud da una precedente /// serializzazione /// </summary> private void DeSerialize() { try { Account = null; string data = File.ReadAllText(SerializationFileName, Encoding.UTF8); EncDecHelper encDecHelper = new EncDecHelper { PasswordString = SerializationPassword }; Xamarin.Auth.Account account = Xamarin.Auth.Account.Deserialize(encDecHelper.AESDecrypt(data, out bool warning)); if (warning) { Debug.Write(string.Format("Google Drive serialize file {0}. File seems to be corrupted. I have tried to recover the data.", SerializationFileName)); } if (account != null) { Account = new OAuthAccountWrapper(account); RememberMe = true; } } catch (FileNotFoundException) { // Accettabile Debug.WriteLine(string.Format("Deserialize: file {0} not found", SerializationFileName)); } catch (Exception Ex) { Debug.WriteLine("Deserialize error: " + Ex.Message); } }
/// <summary> /// Restituisce il codice di backup da utilizzare in caso non sia possibile /// generare il token temporale. /// </summary> /// <returns>Codice di backup per l'accesso</returns> public string GetBackupCode() { RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider(); byte[] data = new byte[20]; rngCsp.GetBytes(data); string hash = EncDecHelper.MD5(data); string code = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(hash)).ToUpper(); for (int i = 1; i < 4; i++) { code = code.Insert(i * 8 + (i - 1), "-"); } return(code); }
/// <summary> /// Restituisce una password che dipende dal dispositivo /// </summary> /// <returns>Password</returns> private byte[] GetDevicePwd() { string defDeviceId = FakeDeviceId; string pwd = SaltDevicePwd; try { pwd += new DeviceInfo().GetDeviceID(); } catch (Exception ex) { // API non trovate o non funzionanti Debug.WriteLine("GetDevicePwd failed. Error: " + ex.Message); pwd += defDeviceId + "napi"; } return(EncDecHelper.SHA256Bytes(pwd)); }
public async Task Init(string AppId, Uri url, Func <NotificationInfo, Task <bool> > pushNotificationOpened) { OneSignalAppId = AppId; OneSignalUrl = url; try { StorageFolder localFolder = ApplicationData.Current.LocalFolder; StorageFile pushNotificationFile = await localFolder.GetFileAsync("push.notification"); if (pushNotificationFile != null) { string content = await FileIO.ReadTextAsync(pushNotificationFile, Windows.Storage.Streams.UnicodeEncoding.Utf8); if (content.Length > 0) { EncDecHelper encDecHelper = new EncDecHelper { Password = GetDevicePwd() }; string decryptedContent = encDecHelper.AESDecrypt(content, out bool warning); if (decryptedContent.Length > 0) { JObject json = JObject.Parse(decryptedContent); PushNotificationToken = json.Value <string>("token"); PushNotificationDeviceID = json.Value <string>("playerid"); } } } } catch (FileNotFoundException) { // Il file non esiste PushNotificationToken = ""; PushNotificationDeviceID = ""; } catch (Exception ex) { PushNotificationToken = ""; PushNotificationDeviceID = ""; Debug.WriteLine("Errore durante la lettura del file di configurazione delle notifiche push. Exception: " + ex.Message); throw; } }
/// <summary> /// Serializzazione delle informazioni di accesso al Cloud su file /// </summary> private void Serialize() { if (!IsLoggedIn()) { return; } try { string data = Account.OAuthAccount.Serialize(); EncDecHelper encDecHelper = new EncDecHelper { PasswordString = SerializationPassword }; File.WriteAllText(SerializationFileName, encDecHelper.AESEncrypt(data), System.Text.Encoding.UTF8); } catch (Exception Ex) { Debug.WriteLine("Serialize error: " + Ex.Message); } }
public async void StartAuthentication(string clientId, string scope, string appSecret, Uri authorizeUrl, Uri redirectUrl, Uri tokenUrl, bool codeChallengeMethod) { string codeVerifier = ""; UriBuilder uriBuilder = new UriBuilder(authorizeUrl); uriBuilder.Query += "?client_id=" + clientId + "&scope=" + Uri.EscapeUriString(scope) + "&response_type=code&redirect_uri=" + Uri.EscapeUriString(redirectUrl.AbsoluteUri); // Codice opzionale di sicurezza if (codeChallengeMethod) { codeVerifier = GetCodeVerifier(); string codeChallenge = Base64URLEncode(EncDecHelper.SHA256Bytes(codeVerifier)); uriBuilder.Query += "&code_challenge_method=S256&code_challenge=" + codeChallenge; } try { // Step 1: richiede il codice di autorizzazione WebAuthenticationResult Result = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, uriBuilder.Uri, redirectUrl); if (Result.ResponseStatus == WebAuthenticationStatus.Success) { Account account = new Account(); // Estraggo il codice string Code = ""; string QueryString = new Uri(Result.ResponseData).Query; QueryString = QueryString.Substring(1); // Salta "?" string[] QueryParams = QueryString.Split('&'); for (short i = 0; i < QueryParams.Length; i++) { if (QueryParams[i].Contains("code=")) { Code = QueryParams[i].Substring(5); break; } } // Step 2: scambio il codice con un access token HttpClient appClient = new HttpClient(); try { List <KeyValuePair <string, string> > Param = new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>("client_id", clientId), new KeyValuePair <string, string>("redirect_uri", Uri.EscapeUriString(redirectUrl.AbsoluteUri)), new KeyValuePair <string, string>("code", Uri.EscapeUriString(Code)), new KeyValuePair <string, string>("scope", scope), new KeyValuePair <string, string>("grant_type", "authorization_code") }; // Non è obbligatorio in certi casi (es: Google Drive API per iOS, Android e UWP) if (appSecret != "") { Param.Add(new KeyValuePair <string, string>("client_secret", appSecret)); } // Codice opzionale di verifica if (codeChallengeMethod && codeVerifier != "") { Param.Add(new KeyValuePair <string, string>("code_verifier", codeVerifier)); } FormUrlEncodedContent Content = new FormUrlEncodedContent(Param); HttpResponseMessage Response = await appClient.PostAsync(tokenUrl, Content); if (Response.IsSuccessStatusCode) { // Ottengo un JSON con l'access token, il refesh token e la scadenza. string content = await Response.Content.ReadAsStringAsync(); JObject JsonObj = JObject.Parse(content); if (JsonObj != null && JsonObj.ContainsKey("access_token")) { foreach (KeyValuePair <string, JToken> token in JsonObj) { account.Properties.Add(token.Key, token.Value.ToString()); } account.Properties.Add("date_token", DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss")); // Step 3: richiedo un nuovo access token e un refresh token per aggiornare il // token (in quando voglio accedere offline alla cartella di OneDrive) OAuthAccountWrapper oAuthAccount = new OAuthAccountWrapper(account); await RefreshToken(oAuthAccount, clientId, redirectUrl, appSecret, tokenUrl); if (oAuthAccount.AccessToken.Length <= 0) { appClient.Dispose(); Debug.WriteLine("Authetication failed: access token not found in response"); throw new Exception("Access token not found in response"); } appClient.Dispose(); Debug.WriteLine("Authetication succeeded!"); } else { appClient.Dispose(); Debug.WriteLine("Authetication failed: malformed response"); throw new Exception("Malformed response"); } } else { appClient.Dispose(); Debug.WriteLine("Authetication failed: " + Response.StatusCode.ToString()); throw new Exception("HTTP Error: " + Response.StatusCode + "\nUnable to redeem a token"); } AuthenticatorCompletedEventArgs AuthCompletedEventArgs = new AuthenticatorCompletedEventArgs(account); Completed?.Invoke(this, AuthCompletedEventArgs); } catch (Exception Ex) { appClient.Dispose(); Debug.WriteLine("Authetication failed: " + Ex.Message); throw; } } else if (Result.ResponseStatus != WebAuthenticationStatus.UserCancel) { Debug.WriteLine("Authetication failed: " + Result.ResponseStatus.ToString()); throw new Exception("HTTP Error code: " + Result.ResponseErrorDetail + "\nError: " + Result.ResponseData); } else { Debug.WriteLine("Authetication cancelled by user"); // Passando null si avrà IsAuthenticated a false. // Vedi https://github.com/xamarin/Xamarin.Auth/blob/master/source/Core/Xamarin.Auth.Common.LinkSource/AuthenticatorCompletedEventArgs.cs AuthenticatorCompletedEventArgs AuthCompletedEventArgs = new AuthenticatorCompletedEventArgs(null); Completed?.Invoke(this, AuthCompletedEventArgs); } } catch (Exception Ex) { Debug.WriteLine("Authetication failed: " + Ex.Message); AuthenticatorErrorEventArgs AuthCompletedEventArgs = new AuthenticatorErrorEventArgs(Ex); Error?.Invoke(this, AuthCompletedEventArgs); } }