Example #1
0
        /// <summary>
        /// Splits a ampersand-separated list of key-value pairs, decodes the keys and
        /// values, and adds them to a NameValueCollection. Keys and values are separated
        /// by equals signs.
        /// </summary>
        /// <param name="input">The key-value pair list</param>
        /// <returns>A name value collection, which may be empty.</returns>
        /// <exception cref="System.FormatException">
        /// If the string is not a series of key-value pairs separated by ampersands,
        /// or if one of the keys is null or empty, or if one of the keys or values is
        /// not properly encoded.
        /// </exception>
        public static NameValueCollection SplitAndDecode(string input)
        {
            NameValueCollection parameters = new NameValueCollection();

            if (string.IsNullOrEmpty(input))
            {
                return(parameters);
            }

            foreach (string pair in input.Split('&'))
            {
                string[] parts = pair.Split('=');

                if (parts.Length != 2)
                {
                    throw new FormatException("Pair is not a key-value pair");
                }

                string key = Rfc3986.Decode(parts[0]);
                if (string.IsNullOrEmpty(key))
                {
                    throw new FormatException("Key cannot be null or empty");
                }

                string value = Rfc3986.Decode(parts[1]);

                parameters.Add(key, value);
            }

            return(parameters);
        }
Example #2
0
        public void Sign(Uri requestUri, string httpMethod, IConsumer consumer, IToken token, ISigningProvider signingProvider)
        {
            if (token != null)
            {
                this.Token = token.Token;
            }

            OAuthParameters signingParameters = this.Clone();
            var             signingUri        = new UriBuilder(requestUri);

            // Normalize the request uri for signing
            if (!string.IsNullOrEmpty(requestUri.Query))
            {
                // TODO: Will the parameters necessarily be Rfc3698 encoded here? If not, then Rfc3968.SplitAndDecode will throw FormatException
                signingParameters.AdditionalParameters.Add(Rfc3986.SplitAndDecode(requestUri.Query.Substring(1)));
                signingUri.Query = null;
            }

            if (signingProvider == null)
            {
                // There is no signing provider for this signature method
                OAuthRequestException.ThrowSignatureMethodRejected(null);
            }

            // Compute the signature
            this.Signature = signingProvider.ComputeSignature(
                SignatureBase.Create(httpMethod, signingUri.Uri, signingParameters),
                consumer.Secret,
                (token != null && token.Secret != null) ? token.Secret : null);
        }
Example #3
0
        /// <summary>
        /// Join the name-value pairs into a string seperated with ampersands.
        /// Each name and value is first RFC 3986 encoded and values are separated
        /// from names with equal signs.
        /// </summary>
        /// <param name="values">The name value collection to encode and join</param>
        /// <returns>An RFC 3986 compliant string</returns>
        public static string EncodeAndJoin(NameValueCollection values)
        {
            if (values == null)
            {
                return(string.Empty);
            }

            StringBuilder enc = new StringBuilder();

            bool first = true;

            foreach (string key in values.Keys)
            {
                string encKey = Rfc3986.Encode(key);
                foreach (string value in values.GetValues(key))
                {
                    if (!first)
                    {
                        enc.Append("&");
                    }
                    else
                    {
                        first = false;
                    }

                    enc.Append(encKey).Append("=").Append(Rfc3986.Encode(value));
                }
            }

            return(enc.ToString());
        }
Example #4
0
        /// <summary>
        /// Creates a normalized representation of the parameters for use in the signature base string.
        /// </summary>
        /// <param name="excludedParameters">Names of parameters to exclude from the normalized string.</param>
        /// <returns>The signature-base normalized representation of the parameters.</returns>
        public string ToNormalizedString(params string[] excludedParameters)
        {
            var @params = new List <KeyValuePair <string, string> >();

            // Add OAuth parameters whose values are not null except excluded parameters
            foreach (var param in this.parameters.Keys)
            {
                if (this.parameters[param] != null && Array.IndexOf <string>(excludedParameters, param) < 0)
                {
                    @params.Add(new KeyValuePair <string, string>(Rfc3986.Encode(param), Rfc3986.Encode(this.parameters[param])));
                }
            }

            // Add all additional parameters
            foreach (var param in this.AdditionalParameters.AllKeys)
            {
                foreach (var value in this.AdditionalParameters.GetValues(param) ?? new string[] { })
                {
                    @params.Add(new KeyValuePair <string, string>(Rfc3986.Encode(param), Rfc3986.Encode(value)));
                }
            }

            // Sort parameters into lexicographic order (by key and value)
            @params.Sort(
                (left, right) =>
                left.Key.Equals(right.Key, StringComparison.Ordinal)
                        ? string.Compare(left.Value, right.Value, StringComparison.Ordinal)
                        : string.Compare(left.Key, right.Key, StringComparison.Ordinal));

            // Concatenate and encode
            string equals    = "=";
            string ampersand = "&";

            StringBuilder parms = new StringBuilder();
            bool          first = true;

            foreach (var pair in @params)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    parms.Append(ampersand);
                }

                parms.Append(pair.Key).Append(equals).Append(pair.Value);
            }

            return(parms.ToString());
        }
Example #5
0
        /// <summary>
        /// Serializes a SimpleToken to a string representation.
        /// </summary>
        /// <param name="token">Token</param>
        /// <returns>String serialization of the token</returns>
        /// <exception cref="System.ArgumentNullException">if <paramref name="token"/> is <c>null</c></exception>
        public static string Serialize(OAuthToken token)
        {
            if (token == null)
            {
                throw new ArgumentNullException("token");
            }

            return("[" + Rfc3986.Encode(Enum.Format(typeof(TokenType), token.Type, "G"))
                   + "|" + Rfc3986.Encode(token.Token)
                   + "|" + Rfc3986.Encode(token.Secret)
                   + "|" + Rfc3986.Encode(token.ConsumerKey)
                   + "]");
        }
Example #6
0
        private static void EncodeHeaderValue(StringBuilder buffer, string key, string value, string separator, bool quote)
        {
            buffer.Append(separator);
            buffer.Append(Rfc3986.Encode(key));
            buffer.Append("=");

            if (quote)
            {
                buffer.Append('"');
            }

            buffer.Append(Rfc3986.Encode(value));

            if (quote)
            {
                buffer.Append('"');
            }
        }
Example #7
0
        public static string Create(string httpMethod, Uri requestUrl, OAuthParameters parameters)
        {
            StringBuilder sigbase = new StringBuilder();

            // Http header
            sigbase.Append(Rfc3986.Encode(httpMethod)).Append("&");

            // Normalized request URL
            sigbase.Append(Rfc3986.Encode(requestUrl.Scheme));
            sigbase.Append(Rfc3986.Encode("://"));
            sigbase.Append(Rfc3986.Encode(requestUrl.Authority.ToLowerInvariant()));
            sigbase.Append(Rfc3986.Encode(requestUrl.AbsolutePath));
            sigbase.Append("&");

            // Normalized parameters
            sigbase.Append(Rfc3986.Encode(parameters.ToNormalizedString(
                                              Constants.RealmParameter,
                                              Constants.SignatureParameter,
                                              Constants.TokenSecretParameter)));

            return(sigbase.ToString());
        }
        /// <summary>
        /// Throws an exception indicating unexpected parameter(s) were received.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        /// The <see cref="Problem">problem type</see> is
        /// <see cref="OAuthRequestExceptionProblemTypes.ParameterRejected">parameter_rejected</see>.
        /// </para>
        ///
        /// <para>
        /// The <see cref="AdditionalParameter">additional parameter</see>
        /// (<see cref="OAuthRequestExceptionParameters.ParametersRejected">oauth_parameters_rejected</see>)
        /// of the exception consists of a set of parameters, encoded as they would be
        /// in a URL query string. These are parameters that the sender recently
        /// received but doesn't understand. Note that these parameters will be
        /// percent-encoded twice: once to form a query string and again because
        /// the query string is the value of <see cref="OAuthRequestExceptionParameters.ParametersRejected">oauth_parameters_rejected</see>.
        /// </para>
        ///
        /// <para>
        /// The <paramref name="advice"/> parameter, if supplied, will be
        /// stored in the <see cref="Advice"/> property.
        /// </para>
        ///
        /// <para>
        /// The <see cref="Exception.Source"/> will be <see cref="OAuthRequestExceptionSources.Local">local</see>.
        /// </para>
        /// </remarks>
        ///
        /// <param name="parameters">The parameters that are rejected</param>
        /// <param name="advice">(Optional) Plain text advice for the user
        /// of the consumer</param>
        ///
        /// <exception cref="System.ArgumentException">
        /// If <paramref name="parameters"/> is null or empty.
        /// </exception>
        /// <exception cref="OAuth.Net.Common.OAuthRequestException">
        /// On success
        /// </exception>
        public static void ThrowParametersRejected(string[] parameters, string advice)
        {
            if (parameters == null || parameters.Length == 0)
            {
                throw new ArgumentException("parameters argument cannot be null or of length 0", "parameters");
            }

            StringBuilder rejectedParameters = new StringBuilder();

            bool first = true;

            foreach (string parameter in parameters)
            {
                if (!first)
                {
                    rejectedParameters.Append("&");
                }
                else
                {
                    first = false;
                }

                rejectedParameters.Append(Rfc3986.Encode(parameter));
            }

            throw new OAuthRequestException()
                  {
                      Problem = OAuthRequestExceptionProblemTypes.ParameterRejected,

                      AdditionalParameter = new KeyValuePair <string, string>(
                          OAuthRequestExceptionParameters.ParametersRejected, rejectedParameters.ToString()),

                      Advice = advice,

                      Source = OAuthRequestExceptionSources.Local
                  };
        }
Example #9
0
        /*
         * Check for an OAuth Authorization HTTP header and, if present, parse it
         * and add it to the collection
         */
        private static NameValueCollection ParseAuthHeader(string authHeader)
        {
            if (!string.IsNullOrEmpty(authHeader))
            {
                NameValueCollection @params = new NameValueCollection();

                // Check for OAuth auth-scheme
                Match authSchemeMatch = Constants.OAuthCredentialsRegex.Match(authHeader);
                if (authSchemeMatch.Success)
                {
                    // We have OAuth credentials in the Authorization header; parse the parts
                    // Sad-to-say, but this code is much simpler than the regex for it!
                    string[] authParameterValuePairs = authHeader.Substring(authSchemeMatch.Length)
                                                       .Split(',');

                    foreach (string authParameterValuePair in authParameterValuePairs)
                    {
                        string[] parts = authParameterValuePair.Trim().Split('=');

                        if (parts.Length == 2)
                        {
                            string parameter = parts[0];
                            string value     = parts[1];

                            if (value.StartsWith("\"", StringComparison.Ordinal) && value.EndsWith("\"", StringComparison.Ordinal))
                            {
                                value = value.Substring(1, value.Length - 2);

                                try
                                {
                                    value = Constants.StringEscapeSequence.Replace(
                                        value,
                                        (Match match) =>
                                    {
                                        Group group = match.Groups[1];
                                        if (group.Length == 1)
                                        {
                                            switch (group.Value)
                                            {
                                            case "\"": return("\"");

                                            case "'": return("'");

                                            case "\\": return("\\");

                                            case "0": return("\0");

                                            case "a": return("\a");

                                            case "b": return("\b");

                                            case "f": return("\f");

                                            case "n": return("\n");

                                            case "r": return("\r");

                                            case "t": return("\t");

                                            case "v": return("\v");
                                            }
                                        }

                                        return(string.Format(
                                                   CultureInfo.InvariantCulture,
                                                   "{0}",
                                                   char.Parse(group.Value)));
                                    });
                                }
                                catch (FormatException)
                                {
                                    continue;
                                }

                                // Add the parameter and value
                                @params.Add(Rfc3986.Decode(parameter), Rfc3986.Decode(value));
                            }
                        }
                    }
                }

                return(@params);
            }

            return(null);
        }
Example #10
0
        /// <summary>
        /// De-serializes a SimpleToken from its serialized form.
        /// </summary>
        /// <param name="serializedForm">Serialized token</param>
        /// <returns>Token</returns>
        /// <exception cref="System.ArgumentException">
        /// if <paramref name="serializedForm"/> is null or empty
        /// </exception>
        /// <exception cref="System.FormatException">
        /// if <paramref name="serializedForm"/> is not a valid serialized form
        /// </exception>
        public static OAuthToken Deserialize(string serializedForm)
        {
            if (string.IsNullOrEmpty(serializedForm))
            {
                throw new ArgumentException("serializedForm argument must not be null or empty", "serializedForm");
            }

            if (!serializedForm.StartsWith("[", StringComparison.Ordinal))
            {
                throw new FormatException("Serialized SimpleToken must start with [");
            }

            if (!serializedForm.EndsWith("]", StringComparison.Ordinal))
            {
                throw new FormatException("Serialized SimpleToken must end with ]");
            }

            string[] parts = serializedForm.Substring(1, serializedForm.Length - 2)
                             .Split(new char[] { '|' }, StringSplitOptions.None);

            if (parts.Length != 4)
            {
                throw new FormatException("Serialized SimpleToken must consist of 4 pipe-separated fields");
            }

            if (string.IsNullOrEmpty(parts[0]))
            {
                throw new FormatException("Error deserializing SimpleToken.Type (field 0): cannot be null or empty");
            }

            TokenType type;

            try
            {
                type = (TokenType)Enum.Parse(typeof(TokenType), Rfc3986.Decode(parts[0]), true);
            }
            catch (Exception e)
            {
                throw new FormatException("Error deserializing SimpleToken.Type (field 0)", e);
            }

            if (string.IsNullOrEmpty(parts[1]))
            {
                throw new FormatException("Error deserializing SimpleToken.Token (field 1): cannot be null or empty");
            }

            string token;

            try
            {
                token = Rfc3986.Decode(parts[1]);
            }
            catch (Exception e)
            {
                throw new FormatException("Error deserializing SimpleToken.Token (field 1)", e);
            }

            string secret;

            try
            {
                secret = Rfc3986.Decode(parts[2]);
            }
            catch (Exception e)
            {
                throw new FormatException("Error deserializing SimpleToken.Secret (field 2)", e);
            }

            string consumerKey;

            try
            {
                consumerKey = Rfc3986.Decode(parts[3]);
            }
            catch (Exception e)
            {
                throw new FormatException("Error deserializing SimpleToken.ConsumerKey (field 3)", e);
            }

            return(new OAuthToken(type, token, secret, consumerKey));
        }