internal IDictionary <string, string> Serialize(IMessage message) { ErrorUtilities.VerifyArgumentNotNull(message, "message"); var messageDescription = MessageDescription.Get(this.messageType, message.Version); var messageDictionary = new MessageDictionary(message); // Rather than hand back the whole message dictionary (which // includes keys with blank values), create a new dictionary // that only has required keys, and optional keys whose // values are not empty. var result = new Dictionary <string, string>(); foreach (var pair in messageDictionary) { MessagePart partDescription; if (messageDescription.Mapping.TryGetValue(pair.Key, out partDescription)) { if (partDescription.IsRequired || partDescription.IsNondefaultValueSet(message)) { result.Add(pair.Key, pair.Value); } } else { // This is extra data. We always write it out. result.Add(pair.Key, pair.Value); } } return(result); }
/// <summary> /// Verifies that all required message parts are initialized to values /// prior to sending the message to a remote party. /// </summary> /// <param name="message">The message to verify.</param> /// <exception cref="ProtocolException"> /// Thrown when any required message part does not have a value. /// </exception> private static void EnsureValidMessageParts(IProtocolMessage message) { Debug.Assert(message != null, "message == null"); MessageDictionary dictionary = new MessageDictionary(message); MessageDescription description = MessageDescription.Get(message.GetType(), message.Version); description.EnsureMessagePartsPassBasicValidation(dictionary); }
/// <summary> /// Ensures that all message parameters that must be signed are in fact included /// in the signature. /// </summary> /// <param name="signedMessage">The signed message.</param> private static void EnsureParametersRequiringSignatureAreSigned(ITamperResistantOpenIdMessage signedMessage) { // Verify that the signed parameter order includes the mandated fields. // We do this in such a way that derived classes that add mandated fields automatically // get included in the list of checked parameters. Protocol protocol = Protocol.Lookup(signedMessage.Version); var partsRequiringProtection = from part in MessageDescription.Get(signedMessage.GetType(), signedMessage.Version).Mapping.Values where part.RequiredProtection != ProtectionLevel.None select part.Name; ErrorUtilities.VerifyInternal(partsRequiringProtection.All(name => name.StartsWith(protocol.openid.Prefix, StringComparison.Ordinal)), "Signing only works when the parameters start with the 'openid.' prefix."); string[] signedParts = signedMessage.SignedParameterOrder.Split(','); var unsignedParts = from partName in partsRequiringProtection where !signedParts.Contains(partName.Substring(protocol.openid.Prefix.Length)) select partName; ErrorUtilities.VerifyProtocol(!unsignedParts.Any(), OpenIdStrings.SignatureDoesNotIncludeMandatoryParts, string.Join(", ", unsignedParts.ToArray())); }
/// <summary> /// Reads name=value pairs into an OAuth message. /// </summary> /// <param name="fields">The name=value pairs that were read in from the transport.</param> /// <param name="message">The message to deserialize into.</param> /// <exception cref="ProtocolException">Thrown when protocol rules are broken by the incoming message.</exception> internal void Deserialize(IDictionary <string, string> fields, IMessage message) { ErrorUtilities.VerifyArgumentNotNull(fields, "fields"); ErrorUtilities.VerifyArgumentNotNull(message, "message"); // Before we deserialize the message, make sure all the required parts are present. MessageDescription.Get(this.messageType, message.Version).EnsureMessagePartsPassBasicValidation(fields); try { foreach (var pair in fields) { IDictionary <string, string> dictionary = new MessageDictionary(message); dictionary[pair.Key] = pair.Value; } } catch (ArgumentException ex) { throw ErrorUtilities.Wrap(ex, MessagingStrings.ErrorDeserializingMessage, this.messageType.Name); } message.EnsureValidMessage(); }
/// <summary> /// Gets the value to use for the openid.signed parameter. /// </summary> /// <param name="signedMessage">The signable message.</param> /// <returns> /// A comma-delimited list of parameter names, omitting the 'openid.' prefix, that determines /// the inclusion and order of message parts that will be signed. /// </returns> private string GetSignedParameterOrder(ITamperResistantOpenIdMessage signedMessage) { ErrorUtilities.VerifyArgumentNotNull(signedMessage, "signedMessage"); Protocol protocol = Protocol.Lookup(signedMessage.Version); MessageDescription description = MessageDescription.Get(signedMessage.GetType(), signedMessage.Version); var signedParts = from part in description.Mapping.Values where (part.RequiredProtection & System.Net.Security.ProtectionLevel.Sign) != 0 && part.GetValue(signedMessage) != null select part.Name; string prefix = Protocol.V20.openid.Prefix; ErrorUtilities.VerifyInternal(signedParts.All(name => name.StartsWith(prefix, StringComparison.Ordinal)), "All signed message parts must start with 'openid.'."); if (this.opSecuritySettings.SignOutgoingExtensions) { // Tack on any ExtraData parameters that start with 'openid.'. List <string> extraSignedParameters = new List <string>(signedMessage.ExtraData.Count); foreach (string key in signedMessage.ExtraData.Keys) { if (key.StartsWith(protocol.openid.Prefix, StringComparison.Ordinal)) { extraSignedParameters.Add(key); } else { Logger.DebugFormat("The extra parameter '{0}' will not be signed because it does not start with 'openid.'.", key); } } signedParts = signedParts.Concat(extraSignedParameters); } int skipLength = prefix.Length; string signedFields = string.Join(",", signedParts.Select(name => name.Substring(skipLength)).ToArray()); return(signedFields); }