/// <summary>
        /// Calls Twitter with a request token and a verifier, and receives an access token and an access token secret
        /// </summary>
        /// <param name="userRequestToken">request token obtained from Twitter in the first place (see above) </param>
        /// <param name="userVerifier">corresponds to <c>oauth_verifier</c> in Step 2 of Token sign in</param>
        /// <param name="twtrConsumerKey">ConsumerKey issued by Twitter to the calling app.</param>
        /// <param name="twtrConsumerSecret">ConsumerSecret issued by Twitter to the calling app.</param>
        /// <returns>a tuple where the first item is the access token and the second the access token secret</returns>
        private async Task <Tuple <string, string> > GetTwitterAccessTokenAndTokenSecret(string userRequestToken, string userVerifier, string twtrConsumerKey, string twtrConsumerSecret)
        {
            // access token
            string accessToken = null;

            // access token secret
            string accessTokenSecret = null;

            // Response string returned by third party id provider
            string responseString = null;

            // Construct the request token request to Twitter
            TwitterAuthHeader twitterAccessTokenRequest = new TwitterAuthHeader
            {
                SigningKey           = twtrConsumerSecret + "&" + Uri.EscapeDataString(userRequestToken),
                OauthToken           = userRequestToken,
                OauthVerifier        = userVerifier,
                OauthCallback        = twtrAccessTokenURL,
                OauthConsumerKey     = Uri.EscapeDataString(twtrConsumerKey), // must escape the consumer key
                OauthNonce           = OAuthUtil.GeneratePseudoRandomAlphaNumericString(32),
                OauthSignatureMethod = "HMAC-SHA1",
                OauthTimestamp       = OAuthUtil.SecondsSinceBeginningOfTime,
                OauthVersion         = "1.0"
            };

            // Create the outgoing HTTP request
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(twtrAccessTokenURL);

            request.Method = "POST";
            request.Headers["Authorization"] = twitterAccessTokenRequest.AuthHeader(twtrAccessTokenURL, "POST");

            try
            {
                // Parse the incoming response
                WebResponse response = await request.GetResponseAsync();

                using (Stream responseStream = response.GetResponseStream())
                    using (StreamReader r = new StreamReader(responseStream))
                    {
                        responseString = r.ReadToEnd();

                        var responseValues = System.Web.HttpUtility.ParseQueryString(responseString);

                        // Check whether the response is empty
                        if (responseValues == null)
                        {
                            throw new OAuthException(OAuthErrors.ServiceUnavailable_503_Twitter_3);
                        }

                        accessToken       = responseValues["oauth_token"];
                        accessTokenSecret = responseValues["oauth_token_secret"];
                    }
            }
            catch (Exception ex)
            {
                throw new OAuthException(OAuthErrors.ServiceUnavailable_503_Twitter_3, ex);
            }

            return(new Tuple <string, string>(accessToken, accessTokenSecret));
        }
        /// <summary>
        /// Calls Twitter with the access token and access token secret and expects the user profile (aka decodes the token)
        /// </summary>
        /// <param name="accessToken">Twitter user access token</param>
        /// <param name="accessTokenSecret">Twitter user access token secret</param>
        /// <param name="twtrConsumerKey">ConsumerKey issued by Twitter to the calling app.</param>
        /// <param name="twtrConsumerSecret">ConsumerSecret issued by Twitter to the calling app.</param>
        /// <returns>a user profile specific to Twitter</returns>
        private async Task <TwitterProfile> TwitterImplicitFlow(string accessToken, string accessTokenSecret, string twtrConsumerKey, string twtrConsumerSecret)
        {
            // Construct the request token request to Twitter
            TwitterAuthHeader twitterUserProfileRequest = new TwitterAuthHeader
            {
                SigningKey           = twtrConsumerSecret + "&" + accessTokenSecret,
                OauthToken           = accessToken,
                OauthConsumerKey     = Uri.EscapeDataString(twtrConsumerKey), // must escape the consumer key
                OauthNonce           = OAuthUtil.GeneratePseudoRandomAlphaNumericString(32),
                OauthSignatureMethod = "HMAC-SHA1",
                OauthTimestamp       = OAuthUtil.SecondsSinceBeginningOfTime,
                OauthVersion         = "1.0"
            };

            // User profile extracted from the token
            TwitterProfile tokenProfile = null;

            // Response string returned by third party id provider
            string responseString = null;

            // Create the outgoing HTTP request
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(twtrGetProfileURL);

            request.Method = "GET";
            request.Headers["Authorization"] = twitterUserProfileRequest.AuthHeader(twtrGetProfileURL, "GET");

            try
            {
                // Parse the incoming response
                WebResponse response = await request.GetResponseAsync();

                using (Stream responseStream = response.GetResponseStream())
                    using (StreamReader r = new StreamReader(responseStream))
                    {
                        responseString = r.ReadToEnd();
                    }

                if (string.IsNullOrEmpty(responseString))
                {
                    throw new OAuthException(OAuthErrors.ServiceUnavailable_503_Twitter_2);
                }

                tokenProfile = JsonConvert.DeserializeObject <TwitterProfile>(responseString);
            }
            catch (Exception ex)
            {
                throw new OAuthException(OAuthErrors.ServiceUnavailable_503_Twitter_2, ex);
            }

            return(tokenProfile);
        }
        /// <summary>
        /// Constructs the signed request syntax according to Twitter's spec.
        /// </summary>
        /// <param name="url">url for request to Twitter</param>
        /// <param name="method">string representing the HTTP method (GET versus POST)</param>
        /// <returns>the properly formatted HTTP request string.</returns>
        private string SignedHTTPRequest(string url, string method)
        {
            string requestString = string.Empty;

            foreach (PropertyInfo prop in this.GetType().GetProperties())
            {
                object[] attributes = prop.GetCustomAttributes(typeof(TwitterAuthHeaderAttribute), true);
                if (attributes.Length > 0)
                {
                    string propVal = (string)prop.GetValue(this);
                    if (!string.IsNullOrEmpty(propVal))
                    {
                        string propName = ((TwitterAuthHeaderAttribute)attributes[0]).Name;
                        requestString += '&' + propName + "=" + propVal;
                    }
                }
            }

            // The two '&' chars after POST and the TokenURL must stay unescaped, but the rest must be escaped.
            requestString = method + "&" + Uri.EscapeDataString(url) + "&" + Uri.EscapeDataString(requestString.Substring(1));
            return(OAuthUtil.Base64HMACString(requestString, this.SigningKey));
        }