public Object QueryDuoApi(IHttpWebRequestFactory webRequestFactory, string protocol, string path, HttpWebRequestMethod method, IEnumerable<KeyValuePair<string, string>> queryValues)
        {
            var duoWebRequest = CreateSignedDuoWebRequest(webRequestFactory, protocol, path, method, queryValues);

            try
            {
                var duoResponse = duoWebRequest.GetResponse();

                if (duoResponse != null)
                {
                    var responseStream = duoResponse.GetResponseStream();
                    if (responseStream != null)
                    {
                        using (var reader = new StreamReader(responseStream))
                        {
                            var js = new JavaScriptSerializer();
                            var objText = reader.ReadToEnd();
                            return js.DeserializeObject(objText);
                        }
                    }
                }
            }
            catch (WebException exception)
            {
                return null;
            }
            return null;
        }
        public string GetAuthorizationKey(HttpWebRequestMethod method, string path, string queryString)
        {
            var canon = GetCanonRequest(method, _host, path, queryString);
            var signedCanon = SignHmac(_secretKey, canon);

            var authorization = _integrationKey + ":" + signedCanon;
            return Convert.ToBase64String(Encoding.ASCII.GetBytes(authorization));
        }
 private void SignWebRequest(IHttpWebRequest webRequest, HttpWebRequestMethod method, string path, string queryString)
 {
     webRequest.Headers.Add("Authorization", string.Format("Basic {0}", GetAuthorizationKey(method, path, queryString)));
 }
 private IHttpWebRequest CreateDuoWebRequest(IHttpWebRequestFactory webRequestFactory, string protocol, string path, HttpWebRequestMethod method)
 {
     var duoWebRequest = webRequestFactory.Create(new Uri(string.Format(@"{0}://{1}{2}", protocol, _host, path)));
     duoWebRequest.Method = method;
     duoWebRequest.Accept = "application/json";
     duoWebRequest.Timeout = 3 * 60 * 1000;
     return duoWebRequest;
 }
        private IHttpWebRequest CreateSignedDuoWebRequest(IHttpWebRequestFactory webRequestFactory, string protocol, string path, HttpWebRequestMethod method, IEnumerable<KeyValuePair<string, string>> queryValues)
        {
            var duoWebRequest = CreateDuoWebRequest(webRequestFactory, protocol, path, method);

            var safeQueryString = CreateSafeQueryString(queryValues);

            var reg = new Regex(@"%[a-f0-9]{2}");
            var upperUrl = reg.Replace(safeQueryString, m => m.Value.ToUpperInvariant());

            SignWebRequest(duoWebRequest, method, path, upperUrl);

            if (method == HttpWebRequestMethod.POST) SetFormValuesForQuery(duoWebRequest, upperUrl);

            return duoWebRequest;
        }
        /// <summary>
        /// Build up the canon required for signing
        /// </summary>
        /// <param name="method"></param>
        /// <param name="host"></param>
        /// <param name="uri"></param>
        /// <param name="queryString"></param>
        /// <returns></returns>
        private static String GetCanonRequest(HttpWebRequestMethod method, string host, string uri, string queryString)
        {
            var canon = new StringBuilder();

            canon.Append(string.Format("{0}\n", method.ToString().ToUpper()));
            canon.Append(string.Format("{0}\n", host.ToLower()));
            canon.Append(string.Format("{0}\n", uri));
            canon.Append(queryString);

            return canon.ToString();
        }
        private IHttpWebRequest CreateSignedDuoWebRequest(IHttpWebRequestFactory webRequestFactory, string protocol, string path, HttpWebRequestMethod method, IEnumerable<KeyValuePair<string, string>> queryValues)
        {
            var duoWebRequest = CreateDuoWebRequest(webRequestFactory, protocol, path, method);

            var safeQueryString = "message=Your%20PIN%20is%20%3Cpin%3E&phone=%2B447952556282"; // CreateSafeQueryString(queryValues);

            SignWebRequest(duoWebRequest, method, path, safeQueryString);

            if (method == HttpWebRequestMethod.POST) SetFormValuesForQuery(duoWebRequest, safeQueryString);

            return duoWebRequest;
        }
        /// <summary>
        /// Build up the canon required for signing
        /// </summary>
        /// <param name="method"></param>
        /// <param name="host"></param>
        /// <param name="uri"></param>
        /// <param name="queryString"></param>
        /// <returns></returns>
        private static String GetCanonRequest(DateTime date, HttpWebRequestMethod method, string host, string uri, string queryString)
        {
            var canon = new StringBuilder();

            canon.Append(string.Format("{0}\n", date.ToUniversalTime().ToString(new System.Globalization.DateTimeFormatInfo().RFC1123Pattern)));
            canon.Append(string.Format("{0}\n", method.ToString().ToUpper()));
            canon.Append(string.Format("{0}\n", host.ToLower()));
            canon.Append(string.Format("{0}\n", uri));
            canon.Append(queryString);

            return canon.ToString();
        }
 private void SignWebRequest(IHttpWebRequest webRequest, HttpWebRequestMethod method, string path, string queryString)
 {
     DateTime now = DateTime.Now;
     webRequest.Headers.Add("Authorization", string.Format("Basic {0}", GetAuthorizationKey(method, now, path, queryString)));
     webRequest.Date = now;
 }
        private IHttpWebRequest CreateSignedDuoWebRequest(IHttpWebRequestFactory webRequestFactory, string protocol, string path, HttpWebRequestMethod method, IEnumerable<KeyValuePair<string, string>> queryValues)
        {
            queryValues = queryValues.OrderBy(item => item.Key);
            var duoWebRequest = CreateDuoWebRequest(webRequestFactory, protocol, path, method);

            var safeQueryString = CreateSafeQueryString(queryValues);

            SignWebRequest(duoWebRequest, method, path, safeQueryString);

            if (method == HttpWebRequestMethod.POST) SetFormValuesForQuery(duoWebRequest, safeQueryString);

            return duoWebRequest;
        }