/// <summary>
        /// Authenticates request.
        /// </summary>
        /// <param name="headers">Headers collection.</param>
        /// <param name="method">Http verb.</param>
        /// <returns>Authenticated <see cref="IPrincipal"/> instance or <c>null</c> otherwise.</returns>
        public IPrincipal AuthenticateRequest(NameValueCollection headers, string method)
        {
            if (!IsAuthorizationPresent(headers))
            {
                return(null);
            }

            string authStr = headers["Authorization"];

            authStr = authStr.Trim().Substring(7);

            string[] elems;
            // To avoid any issues when parsing CSV string, such as comas included in quoted fields, we use
            // TextFieldParser instead of String.Split here.
            using (StringReader reader = new StringReader(authStr))
            {
                using (TextFieldParser parser = new TextFieldParser(reader))
                {
                    parser.TextFieldType = FieldType.Delimited;
                    parser.SetDelimiters(new string[] { ",", "=" });
                    parser.HasFieldsEnclosedInQuotes = true;
                    parser.TrimWhiteSpace            = true;
                    elems = parser.ReadFields();
                }
            }

            Dictionary <string, string> reqInfo = new Dictionary <string, string>();

            for (int i = 0; i < elems.Length; i += 2)
            {
                reqInfo.Add(elems[i], elems[i + 1]);
            }

            string clientUsername = reqInfo.ContainsKey("username") ? reqInfo["username"] : string.Empty;

            // workaround for Windows Vista Digest Authorization. User name may be submitted in the following format:
            // Machine\\User.
            clientUsername      = clientUsername.Replace("\\\\", "\\");
            reqInfo["username"] = clientUsername;
            string username = clientUsername;
            int    ind      = username.LastIndexOf('\\');

            if (ind > 0)
            {
                username = username.Remove(0, ind + 1);
            }

            PasswordAndRoles par = getPasswordAndRolesByUsernameFunction(username);

            if (par == null)
            {
                return(null);
            }

            string unhashedDigest = generateUnhashedDigest(par.Password, reqInfo, method);
            string hashedDigest   = createMD5HashBinHex(unhashedDigest);

            isNonceStale = !isNonceValid(reqInfo["nonce"]);

            if ((reqInfo["response"] != hashedDigest) || isNonceStale)
            {
                return(null);
            }

            return(new GenericPrincipal(new GenericIdentity(clientUsername, "digest"), par.Roles));
        }
        /// <summary>
        /// Authenticates request.
        /// </summary>
        /// <param name="headers">Headers collection.</param>
        /// <param name="method">Http verb.</param>
        /// <returns>Authenticated <see cref="IPrincipal"/> instance or <c>null</c> otherwise.</returns>
        public IPrincipal AuthenticateRequest(NameValueCollection headers, string method)
        {
            if (!IsAuthorizationPresent(headers))
            {
                return(null);
            }

            string authStr = headers["Authorization"];

            authStr = authStr.Trim().Substring(7);

            //Filling header segments in dictionary.
            Dictionary <string, string> reqInfo = new Dictionary <string, string>();
            MatchCollection             matches = Regex.Matches(authStr, "([a-zA-Z0-9]+)=(([^\",]+)|(\\\"([^\"]*)\\\")),?");

            // Group 1 - Param name
            // Group 2 - Whole value string
            // Group 3 - Value if not in "\"" e.g. alg=MD5
            // Group 5 - Value if in "\"" e.g. name="name"
            foreach (Match match in matches)
            {
                string value = match.Groups[5].Value;
                if (value.Length == 0)
                {
                    value = match.Groups[3].Value;
                }
                reqInfo.Add(match.Groups[1].Value, value);
            }

            string clientUsername = reqInfo.ContainsKey("username") ? reqInfo["username"] : string.Empty;

            // workaround for Windows Vista Digest Authorization. User name may be submitted in the following format:
            // Machine\\User.
            clientUsername      = clientUsername.Replace("\\\\", "\\");
            reqInfo["username"] = clientUsername;
            string username = clientUsername;
            int    ind      = username.LastIndexOf('\\');

            if (ind > 0)
            {
                username = username.Remove(0, ind + 1);
            }

            PasswordAndRoles par = getPasswordAndRolesByUsernameFunction(username);

            if (par == null)
            {
                return(null);
            }

            string unhashedDigest = generateUnhashedDigest(par.Password, reqInfo, method);
            string hashedDigest   = createMD5HashBinHex(unhashedDigest);

            isNonceStale = !isNonceValid(reqInfo["nonce"]);

            if ((reqInfo["response"] != hashedDigest) || isNonceStale)
            {
                return(null);
            }

            return(new GenericPrincipal(new GenericIdentity(clientUsername, "digest"), par.Roles));
        }