/// <summary>
        /// Generates an OAuth header.
        /// </summary>
        /// <param name="uri">The URI of the request</param>
        /// <param name="httpMethod">The http method</param>
        /// <param name="parameters">The OAuth parameters</param>
        /// <returns>The OAuth authorization header</returns>
        public static string GenerateHeader(Uri uri, string httpMethod, OAuthParameters parameters)
        {
            parameters.Timestamp = OAuthBase.GenerateTimeStamp();
            parameters.Nonce     = OAuthBase.GenerateNonce();

            string signature = OAuthBase.GenerateSignature(uri, httpMethod, parameters);

            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("Authorization: OAuth {0}=\"{1}\",", OAuthBase.OAuthVersionKey, OAuthBase.OAuthVersion);
            sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthNonceKey, OAuthBase.EncodingPerRFC3986(parameters.Nonce));
            sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthTimestampKey, OAuthBase.EncodingPerRFC3986(parameters.Timestamp));
            sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthConsumerKeyKey, OAuthBase.EncodingPerRFC3986(parameters.ConsumerKey));
            if (parameters.BaseProperties.ContainsKey(OAuthBase.OAuthVerifierKey))
            {
                sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthVerifierKey, OAuthBase.EncodingPerRFC3986(parameters.BaseProperties[OAuthBase.OAuthVerifierKey]));
            }

            if (!String.IsNullOrEmpty(parameters.Token))
            {
                sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthTokenKey, OAuthBase.EncodingPerRFC3986(parameters.Token));
            }

            if (parameters.BaseProperties.ContainsKey(OAuthBase.OAuthCallbackKey))
            {
                sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthCallbackKey, OAuthBase.EncodingPerRFC3986(parameters.BaseProperties[OAuthBase.OAuthCallbackKey]));
            }

            sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthSignatureMethodKey, OAuthBase.HMACSHA1SignatureType);
            sb.AppendFormat("{0}=\"{1}\"", OAuthBase.OAuthSignatureKey, OAuthBase.EncodingPerRFC3986(signature));

            return(sb.ToString());
        }
        /// <summary>
        /// Generates the url which the user should visit in order to authenticate and
        /// authorize with the Service Provider.
        /// When successful, updates the OAuthParameter instance passed as parameter by setting
        /// Token and TokenSecret.
        /// </summary>
        /// <param name="parameters">The OAuth parameters</param>
        /// <returns>The full authorization url the user should visit</returns>
        public static string CreateUserAuthorizationUrl(OAuthParameters parameters)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(userAuthorizationUrl);
            sb.AppendFormat("?{0}={1}", OAuthBase.OAuthTokenKey, OAuthBase.EncodingPerRFC3986(parameters.Token));
            if (!string.IsNullOrEmpty(parameters.Callback))
            {
                sb.AppendFormat("&{0}={1}", OAuthBase.OAuthCallbackKey, OAuthBase.EncodingPerRFC3986(parameters.Callback));
            }

            return(sb.ToString());
        }
        /// <summary>
        /// Generates the url which the user should visit in order to authenticate and
        /// authorize with the Service Provider.
        /// When successful, updates the OAuth2Parameters instance passed as parameter by setting
        /// the returned access code.
        /// </summary>
        /// <param name="parameters">The OAuth 2.0 parameters</param>
        /// <returns>The full authorization url the user should visit</returns>
        public static string CreateOAuth2AuthorizationUrl(OAuth2Parameters parameters)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(parameters.AuthUri);

            sb.AppendFormat("?{0}={1}", OAuthBase.OAuth2ResponseType, OAuthBase.EncodingPerRFC3986(parameters.ResponseType));
            sb.AppendFormat("&{0}={1}", OAuthBase.OAuth2ClientId, OAuthBase.EncodingPerRFC3986(parameters.ClientId));
            sb.AppendFormat("&{0}={1}", OAuthBase.OAuth2RedirectUri, OAuthBase.EncodingPerRFC3986(parameters.RedirectUri));
            sb.AppendFormat("&{0}={1}", OAuthBase.OAuthScopeKey, OAuthBase.EncodingPerRFC3986(parameters.Scope));
            sb.AppendFormat("&{0}={1}", OAuthBase.OAuth2AccessType, OAuthBase.EncodingPerRFC3986(parameters.AccessType));
            sb.AppendFormat("&{0}={1}", OAuthBase.OAuth2ApprovalPrompt, OAuthBase.EncodingPerRFC3986(parameters.ApprovalPrompt));
            if (!string.IsNullOrEmpty(parameters.State))
            {
                sb.AppendFormat("&{0}={1}", OAuthBase.OAuth2State, OAuthBase.EncodingPerRFC3986(parameters.State));
            }

            return(sb.ToString());
        }
        /// <summary>
        /// Contacts Google for a request token, first step of the OAuth authentication process.
        /// When successful, updates the OAuthParameter instance passed as parameter by setting
        /// Token and TokenSecret.
        /// </summary>
        /// <param name="parameters">The OAuth parameters</param>
        public static void GetUnauthorizedRequestToken(OAuthParameters parameters)
        {
            Uri requestUri = new Uri(string.Format("{0}?scope={1}", requestTokenUrl, OAuthBase.EncodingPerRFC3986(parameters.Scope)));

            // callback is only needed when getting the request token
            bool callbackExists = false;

            if (!string.IsNullOrEmpty(parameters.Callback))
            {
                parameters.BaseProperties.Add(OAuthBase.OAuthCallbackKey, parameters.Callback);
                callbackExists = true;
            }

            string     headers = GenerateHeader(requestUri, "GET", parameters);
            WebRequest request = WebRequest.Create(requestUri);

            request.Headers.Add(headers);

            WebResponse response = request.GetResponse();
            string      result   = "";

            if (response != null)
            {
                Stream       responseStream = response.GetResponseStream();
                StreamReader reader         = new StreamReader(responseStream);
                result = reader.ReadToEnd();
            }

            if (callbackExists)
            {
                parameters.BaseProperties.Remove(OAuthBase.OAuthCallbackKey);
            }

            // split results and update parameters
            SortedDictionary <string, string> responseValues = OAuthBase.GetQueryParameters(result);

            parameters.Token       = responseValues[OAuthBase.OAuthTokenKey];
            parameters.TokenSecret = responseValues[OAuthBase.OAuthTokenSecretKey];
        }