/// <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); }
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); }
/// <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()); }
/// <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()); }
/// <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) + "]"); }
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('"'); } }
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 }; }
/* * 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); }
/// <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)); }