/// <summary> /// Constructs the OAuth Signature Base String and returns the result. /// </summary> /// <param name="message">The message to derive the signature base string from.</param> /// <returns>The signature base string.</returns> /// <remarks> /// This method implements OAuth 1.0 section 9.1. /// </remarks> protected static string ConstructSignatureBaseString(ITamperResistantOAuthMessage message) { if (String.IsNullOrEmpty(message.HttpMethod)) { throw new ArgumentException( string.Format( CultureInfo.CurrentCulture, MessagingStrings.ArgumentPropertyMissing, typeof(ITamperResistantOAuthMessage).Name, "HttpMethod"), "message"); } List <string> signatureBaseStringElements = new List <string>(3); signatureBaseStringElements.Add(message.HttpMethod.ToUpperInvariant()); UriBuilder endpoint = new UriBuilder(message.Recipient); endpoint.Query = null; endpoint.Fragment = null; signatureBaseStringElements.Add(endpoint.Uri.AbsoluteUri); var encodedDictionary = OAuthChannel.GetUriEscapedParameters(message); encodedDictionary.Remove("oauth_signature"); var sortedKeyValueList = new List <KeyValuePair <string, string> >(encodedDictionary); sortedKeyValueList.Sort(SignatureBaseStringParameterComparer); StringBuilder paramBuilder = new StringBuilder(); foreach (var pair in sortedKeyValueList) { if (paramBuilder.Length > 0) { paramBuilder.Append("&"); } paramBuilder.Append(pair.Key); paramBuilder.Append('='); paramBuilder.Append(pair.Value); } signatureBaseStringElements.Add(paramBuilder.ToString()); StringBuilder signatureBaseString = new StringBuilder(); foreach (string element in signatureBaseStringElements) { if (signatureBaseString.Length > 0) { signatureBaseString.Append("&"); } signatureBaseString.Append(Uri.EscapeDataString(element)); } Logger.DebugFormat("Constructed signature base string: {0}", signatureBaseString); return(signatureBaseString.ToString()); }
internal static string ConstructSignatureBaseString(ITamperResistantOAuthMessage message, MessageDictionary messageDictionary) { Requires.NotNull(message, "message"); Requires.NotNull(message.HttpMethod, "message.HttpMethod"); Requires.NotNull(messageDictionary, "messageDictionary"); ErrorUtilities.VerifyInternal(messageDictionary.Message == message, "Message references are not equal."); List <string> signatureBaseStringElements = new List <string>(3); signatureBaseStringElements.Add(message.HttpMethod.ToString().ToUpperInvariant()); // For multipart POST messages, only include the message parts that are NOT // in the POST entity (those parts that may appear in an OAuth authorization header). var encodedDictionary = new Dictionary <string, string>(); IEnumerable <KeyValuePair <string, string> > partsToInclude = Enumerable.Empty <KeyValuePair <string, string> >(); var binaryMessage = message as IMessageWithBinaryData; if (binaryMessage != null && binaryMessage.SendAsMultipart) { HttpDeliveryMethods authHeaderInUseFlags = HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest; ErrorUtilities.VerifyProtocol((binaryMessage.HttpMethods & authHeaderInUseFlags) == authHeaderInUseFlags, OAuthStrings.MultipartPostMustBeUsedWithAuthHeader); // Include the declared keys in the signature as those will be signable. // Cache in local variable to avoid recalculating DeclaredKeys in the delegate. ICollection <string> declaredKeys = messageDictionary.DeclaredKeys; partsToInclude = messageDictionary.Where(pair => declaredKeys.Contains(pair.Key)); } else { partsToInclude = messageDictionary; } // If this message was deserialized, include only those explicitly included message parts (excludes defaulted values) // in the signature. var originalPayloadMessage = (IMessageOriginalPayload)message; if (originalPayloadMessage.OriginalPayload != null) { partsToInclude = partsToInclude.Where(pair => originalPayloadMessage.OriginalPayload.ContainsKey(pair.Key)); } foreach (var pair in OAuthChannel.GetUriEscapedParameters(partsToInclude)) { encodedDictionary[pair.Key] = pair.Value; } // An incoming message will already have included the query and form parameters // in the message dictionary, but an outgoing message COULD have SOME parameters // in the query that are not in the message dictionary because they were included // in the receiving endpoint (the original URL). // In an outgoing message, the POST entity can only contain parameters if they were // in the message dictionary, so no need to pull out any parameters from there. if (message.Recipient.Query != null) { NameValueCollection nvc = HttpUtility.ParseQueryString(message.Recipient.Query); foreach (string key in nvc) { string escapedKey = MessagingUtilities.EscapeUriDataStringRfc3986(key); string escapedValue = MessagingUtilities.EscapeUriDataStringRfc3986(nvc[key]); string existingValue; if (!encodedDictionary.TryGetValue(escapedKey, out existingValue)) { encodedDictionary.Add(escapedKey, escapedValue); } else { ErrorUtilities.VerifyInternal(escapedValue == existingValue, "Somehow we have conflicting values for the '{0}' parameter.", escapedKey); } } } encodedDictionary.Remove("oauth_signature"); UriBuilder endpoint = new UriBuilder(message.Recipient); endpoint.Query = null; endpoint.Fragment = null; signatureBaseStringElements.Add(endpoint.Uri.AbsoluteUri); var sortedKeyValueList = new List <KeyValuePair <string, string> >(encodedDictionary); sortedKeyValueList.Sort(SignatureBaseStringParameterComparer); StringBuilder paramBuilder = new StringBuilder(); foreach (var pair in sortedKeyValueList) { if (paramBuilder.Length > 0) { paramBuilder.Append("&"); } paramBuilder.Append(pair.Key); paramBuilder.Append('='); paramBuilder.Append(pair.Value); } signatureBaseStringElements.Add(paramBuilder.ToString()); StringBuilder signatureBaseString = new StringBuilder(); foreach (string element in signatureBaseStringElements) { if (signatureBaseString.Length > 0) { signatureBaseString.Append("&"); } signatureBaseString.Append(MessagingUtilities.EscapeUriDataStringRfc3986(element)); } Logger.Bindings.DebugFormat("Constructed signature base string: {0}", signatureBaseString); return(signatureBaseString.ToString()); }