/// <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> /// 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); }