/// <summary> /// Query Mozilla's FireFox Monitor website to determine if the given email address has been pwned. /// </summary> private async Task <string> GetBreachesWebPageAsync(SecureString emailAddress, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); using (var handler = new HttpClientHandler()) { handler.CookieContainer = new CookieContainer(); handler.UseCookies = true; using (var httpClient = new HttpClient(handler)) { var html = string.Empty; using (HttpResponseMessage response = await httpClient.GetAsync(new Uri(FirefoxMonitorUrl), cancellationToken).ConfigureAwait(false)) { if (response.StatusCode != HttpStatusCode.OK) { throw new Exception($"Unable to load the page: {response.StatusCode.ToString()}"); } html = await response.Content.ReadAsStringAsync().ConfigureAwait(false); } int crsfLocation = html.IndexOf(CrsfIdentifier, StringComparison.OrdinalIgnoreCase); if (crsfLocation < 0) { throw new Exception("Unable to find CSRF token."); } crsfLocation += CrsfIdentifier.Length; string csrf = html.Substring(crsfLocation, html.IndexOf("\"", crsfLocation, StringComparison.Ordinal) - crsfLocation); string emailAddressSha1 = _serializationProvider.GetSha1Hash(emailAddress.ToUnsecureString()); var httpPostParameters = new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>("_csrf", csrf), new KeyValuePair <string, string>("pageToken", string.Empty), new KeyValuePair <string, string>("scannedEmailId", "1"), new KeyValuePair <string, string>("email", emailAddress.ToUnsecureString()), new KeyValuePair <string, string>("emailHash", emailAddressSha1) }; using (var content = new FormUrlEncodedContent(httpPostParameters)) using (HttpResponseMessage response = await httpClient.PostAsync(new Uri(FirefoxMonitorScanUrl), content, cancellationToken).ConfigureAwait(false)) { if (response.StatusCode != HttpStatusCode.OK) { throw new Exception($"Unable to load the result page: {response.StatusCode.ToString()}"); } return(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); } } } }