Here are the important parts of my code.
Custom Message Inspector
Public Class MyCustomMessageInspector
Implements IClientMessageInspector
Public Sub AfterReceiveReply(ByRef reply As
System.ServiceModel.Channels.Message, ByVal correlationState As Object)
Implements
System.ServiceModel.Dispatcher.IClientMessageInspector.AfterReceiveReply
'nothing
End Sub
Public Function BeforeSendRequest(ByRef request As
System.ServiceModel.Channels.Message, ByVal channel As
System.ServiceModel.IClientChannel) As Object Implements
System.ServiceModel.Dispatcher.IClientMessageInspector.BeforeSendRequest
request.Headers.Add(New CustomABCSoapHeader("heliolo"))
Return request
End Function
End Class
Here is my custom message header class.
Public Class CustomABCSoapHeader
Inherits MessageHeader
Dim val As String
Protected Overrides Sub OnWriteHeaderContents(ByVal writer As
Xml.XmlDictionaryWriter, ByVal messageVersion As MessageVersion)
writer.WriteAttributeString("name", CustomABC)
End Sub 'OnWriteHeaderContents
Public Sub New(ByVal value As String)
Me.CustomABC = value
End Sub
<MessageHeader(ProtectionLevel:=System.Net.Security.ProtectionLevel.Sign)> _
Public Property CustomABC() As String
Get
Return val
End Get
Set(ByVal value As String)
val = value
End Set
End Property
Public Overrides ReadOnly Property Name() As String
Get
Return "CustomABC"
End Get
End Property
Public Overrides ReadOnly Property [Namespace]() As String
Get
Return "http://abc.com"
End Get
End Property
End Class 'MyMessageHeader
Here is my Custom Endpoint Behavior.
Public Class MyCustomBehavior
Implements IEndpointBehavior
Public Sub AddBindingParameters(ByVal endpoint As
System.ServiceModel.Description.ServiceEndpoint, ByVal bindingParameters As
System.ServiceModel.Channels.BindingParameterCollection) Implements
System.ServiceModel.Description.IEndpointBehavior.AddBindingParameters
End Sub
Public Sub ApplyClientBehavior(ByVal endpoint As
System.ServiceModel.Description.ServiceEndpoint, ByVal clientRuntime As
System.ServiceModel.Dispatcher.ClientRuntime) Implements
System.ServiceModel.Description.IEndpointBehavior.ApplyClientBehavior
clientRuntime.MessageInspectors.Add(New MyCustomMessageInspector)
End Sub
Public Sub ApplyDispatchBehavior(ByVal endpoint As
System.ServiceModel.Description.ServiceEndpoint, ByVal endpointDispatcher As
System.ServiceModel.Dispatcher.EndpointDispatcher) Implements
System.ServiceModel.Description.IEndpointBehavior.ApplyDispatchBehavior
End Sub
Public Sub Validate(ByVal endpoint As
System.ServiceModel.Description.ServiceEndpoint) Implements
System.ServiceModel.Description.IEndpointBehavior.Validate
End Sub
End Class
And finally here is my client code.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.Windows.RoutedEventArgs) Handles Button1.Click
Dim myws As New MyWS.MyWSSoapClient
Try
myws.ChannelFactory.Credentials.ClientCertificate.SetCertificate( _
"cn=customcertnamehere", _
System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, _
System.Security.Cryptography.X509Certificates.StoreName.My)
myws.ChannelFactory.Endpoint.Behaviors.Add(New MyCustomBehavior())
TextBox1.Text = myws.WSOperation1("Hello world...sign me please.")
Catch ex As Exception
MsgBox(ex.ToString, MsgBoxStyle.OkOnly, "error")
End Try
End Sub
Thanks for any help you can provide.
--
Mike Logan
From your description, you're trying to programmatically add some
soapheaders into WCF message and also want to sign them, correct?
Based on my research, here are some findings and suggestion about custom
WCF header and message securing:
** for message signing(entire message or part of message), you need to use
a binding that support Message layer security(WS-security) and also
configure it to use message layer security
** If you want to add a custom soapheader and only sign that header, the
reasonable approach is first define a "MessageContract" for your WCF
service, and then apply "ProtectionLevel" for each part of the
MessageContract(body or headers).
e.g.
==================
[MessageContract]
public class PatientRecord
{
[MessageHeader(ProtectionLevel=None)] public int recordID;
[MessageHeader(ProtectionLevel=Sign)] public string patientName;
[MessageHeader(ProtectionLevel=EncryptAndSign)] public string SSN;
[MessageBodyMember(ProtectionLevel=None)] public string comments;
[MessageBodyMember(ProtectionLevel=Sign)] public string diagnosis;
[MessageBodyMember(ProtectionLevel=EncryptAndSign)] public string
medicalHistory;
}
===================
#Using Message Contracts
http://msdn.microsoft.com/en-us/library/ms730255.aspx
** For adding custom soap header, in addition to add it via
"MessageInspector", you can also use "OperationContextScope" so that you
can add custom header at client application code. e.g.
=====================
CalcSVC.CalcServiceClient client = new CalcSVC.CalcServiceClient();
using (OperationContextScope opScope = new
OperationContextScope((IContextChannel)client.InnerChannel))
{
OperationContext op = OperationContext.Current;
//add a custom header
SimpleCredentialsHeader credheader = new
SimpleCredentialsHeader();
credheader.Username = "steven"; credheader.Password =
"password";
op.OutgoingMessageHeaders.Add(credheader);
string desc = client.GetDescription();
Console.WriteLine(desc);
}
============================
#How do I add a custom header to every WCF message
http://weblogs.asp.net/avnerk/archive/2006/04/25/How-do-I-add-a-custom-heade
r-to-every-WCF-message_3F00_.aspx
However, for such cases(you programmtically add header into WCF message),
you cannot utilize the built-in message securing feature(sign and encrypt)
as the header you add into message is not originally defined in the service
contract and the securing channel doesn't have idea to secure them. If you
need to encrypt or sign them, we also need to use code to sign/encrypt them
ourself.
And for "MessageHeaderAttribute", it can only be used on member of a class
which is decorated with "MessageContractAttribute" as mentioned in the
following document. It cannot be used on a custom header class.
#MessageHeaderAttribute Class
http://msdn.microsoft.com/en-us/library/system.servicemodel.messageheaderatt
ribute.aspx
Is defining a custom MessageContract suitable for your case? If not, would
you provide some further info about your problem scenario so that we can
try look for some other ideas on this.
Sincerely,
Steven Cheng
Microsoft MSDN Online Support Lead
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
msd...@microsoft.com.
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.
Note: MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 2 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions. Issues of this
nature are best handled working with a dedicated Microsoft Support Engineer
by contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
>From: =?Utf-8?B?TWlrZSBMb2dhbg==?= <Mike...@community.nospam>
>Subject: Sign custom SOAP Header on outbound call with WCF
>Date: Fri, 13 Feb 2009 04:06:12 -0800
I've performed some further research on this and got some progress. As for
custom header which is added dynamically, one means to secure it is adding
some security protectionRequirement(for message part) dynamically. One
means to do this is defining a custom "ContractBehavior" to customize the
binding parameters. e.g.
==========custom binding behavior==========
public class CustomSecureContractBehavior : IContractBehavior
{
string action;
string header;
string ns;
public CustomSecureContractBehavior(string header, string ns,
string action)
{ this.header = header;
this.ns = ns;
this.action = action;
}
#region IContractBehavior Members
public void AddBindingParameters(ContractDescription
contractDescription, ServiceEndpoint endpoint,
System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
ChannelProtectionRequirements requirements =
bindingParameters.Find<ChannelProtectionRequirements>();
XmlQualifiedName headerName = new XmlQualifiedName(header,ns);
requirements.IncomingSignatureParts.ChannelParts.HeaderTypes.Add(headerName
);
//uncomment below to enable encryption
//requirements.IncomingEncryptionParts.ChannelParts.HeaderTypes.Add(headerNa
me );
}
public void ApplyClientBehavior(ContractDescription
contractDescription, ServiceEndpoint endpoint,
System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ContractDescription
contractDescription, ServiceEndpoint endpoint,
System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime)
{
}
public void Validate(ContractDescription contractDescription,
ServiceEndpoint endpoint)
{
}
#endregion
}
=========================
and you can register it at the client-side on the Endpoint. e.g.
=================
static void RunClient()
{
CalcSVC.CalcServiceClient client = new
CalcSVC.CalcServiceClient();
//add my custom contract behavior
client.Endpoint.Contract.Behaviors.Add(
new
CustomSecureContractBehavior("SimpleCredentialsHeader",
"http://www.test.org/customheaders", "*")
);
//I use message security(username client credential type)
client.ClientCredentials.UserName.UserName = "WCFUser";
client.ClientCredentials.UserName.Password = "[Password]";
using (OperationContextScope opScope = new
OperationContextScope((IContextChannel)client.InnerChannel))
{
OperationContext op = OperationContext.Current;
//here I add my custom message header
SimpleCredentialsHeader credheader = new
SimpleCredentialsHeader();
credheader.Username = "steven"; credheader.Password =
"password";
op.OutgoingMessageHeaders.Add(credheader);
string desc = client.GetDescription();
Console.WriteLine(desc);
}
}
==================
BTW, here is my custom message header's definition for your reference
======================
namespace CustomHeaderLib
{
public class SimpleCredentialsHeader : MessageHeader
{
public string Username { get; set; }
public string Password { get; set; }
public SimpleCredentialsHeader()
{
Username = "Anonymous";
Password = string.Empty;
}
public SimpleCredentialsHeader(string username, string password)
{
Username = username;
Password = password;
}
public override string Name
{
get { return "SimpleCredentialsHeader"; }
}
public override string Namespace
{
get { return "http://www.test.org/customheaders"; }
}
public override bool MustUnderstand
{
get
{
return false;
}
}
protected override void
OnWriteHeaderContents(System.Xml.XmlDictionaryWriter writer, MessageVersion
messageVersion)
{
writer.WriteStartElement("CredentialsContent", Namespace);
writer.WriteAttributeString("username", Username);
writer.WriteAttributeString("password", Password);
writer.WriteEndElement();
}
}
}
===================
If you have anything unclear, please feel free to let me know.
Sincerely,
Steven Cheng
Microsoft MSDN Online Support Lead
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
msd...@microsoft.com.
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.
Note: MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 2 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions. Issues of this
nature are best handled working with a dedicated Microsoft Support Engineer
by contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
>From: stc...@online.microsoft.com ("Steven Cheng")
>Organization: Microsoft
>Date: Mon, 16 Feb 2009 06:29:51 GMT
>Subject: RE: Sign custom SOAP Header on outbound call with WCF
I tried what you suggested and the custom soap header is still not signed.
It's added but not signed. There is one part of this puzzle that may help
you out. I cannot change the service. These services are regular .net 1 and
2 asmx services that have no security on them. It's our service broker that
requires the signed custom soap header.
==================================================
Here is my client code
==================================================
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.Windows.RoutedEventArgs) Handles Button1.Click
Dim vdsi As New DecryptClientProxy.SvcSoapClient
Try
vdsi.ClientCredentials.ClientCertificate.SetCertificate( _
"cn=mlogansc1", _
System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, _
System.Security.Cryptography.X509Certificates.StoreName.My)
Dim mcb As New MyCustomBehavior
vdsi.Endpoint.Contract.Behaviors.Add(mcb)
Using opScope As New
OperationContextScope(DirectCast(vdsi.InnerChannel, IContextChannel))
Dim op As OperationContext = OperationContext.Current
'here I add my custom message header
Dim credheader As New MyCustomSoapHeader("mike")
op.OutgoingMessageHeaders.Add(credheader)
TextBox1.Text = vdsi.Operation1("some text here")
End Using
Catch ex As Exception
MsgBox(ex.ToString, MsgBoxStyle.OkOnly, "error")
End Try
End Sub
==================================================
Here is my custom contract behavior
==================================================
Public Class MyCustomBehavior
Implements IContractBehavior
Public Sub AddBindingParameters(ByVal contractDescription As
ContractDescription, ByVal endpoint As ServiceEndpoint, ByVal
bindingParameters As System.ServiceModel.Channels.BindingParameterCollection)
Implements IContractBehavior.AddBindingParameters
Dim requirements As ChannelProtectionRequirements =
bindingParameters.Find(Of ChannelProtectionRequirements)()
Dim headerName As New Xml.XmlQualifiedName("custom_name",
"http://someplace.com")
requirements.IncomingSignatureParts.ChannelParts.HeaderTypes.Add(headerName)
End Sub
Public Sub ApplyClientBehavior(ByVal contractDescription As
ContractDescription, ByVal endpoint As ServiceEndpoint, ByVal clientRuntime
As System.ServiceModel.Dispatcher.ClientRuntime) Implements
IContractBehavior.ApplyClientBehavior
End Sub
Public Sub ApplyDispatchBehavior(ByVal contractDescription As
ContractDescription, ByVal endpoint As ServiceEndpoint, ByVal dispatchRuntime
As System.ServiceModel.Dispatcher.DispatchRuntime) Implements
IContractBehavior.ApplyDispatchBehavior
End Sub
Public Sub Validate(ByVal contractDescription As
ContractDescription, ByVal endpoint As ServiceEndpoint) Implements
IContractBehavior.Validate
End Sub
End Class
==================================================
And finally here is my custom header
==================================================
Public Class MyCustomSoapHeader
Inherits MessageHeader
Dim val As String
Protected Overrides Sub OnWriteHeaderContents(ByVal writer As
Xml.XmlDictionaryWriter, ByVal messageVersion As MessageVersion)
writer.WriteAttributeString("name", VITAUser)
End Sub 'OnWriteHeaderContents
Public Sub New(ByVal value As String)
Me.CustomValue = value
End Sub
Public Property CustomValue() As String
Get
Return val
End Get
Set(ByVal value As String)
val = value
End Set
End Property
Public Overrides ReadOnly Property Name() As String
Get
Return "custom_name"
End Get
End Property
Public Overrides ReadOnly Property [Namespace]() As String
Get
Return "http://someplace.com"
End Get
End Property
Public Shadows ReadOnly Property MustUnderstand() As Boolean
Get
Return False
I think the code you used should be ok and for the custome contractBehavior
approach I mentioned, you only need to configure the extension at
client-side(do not need to modify service). However, onething very
important is the current binding your service using. Your sevice should be
using some binding that support message layer security and my test are
using the default "wsHttpBinding" setting.
I've build a new test client that use certificate client credentials to
call a service secured via wshttpbinding. Here is the VB.NET version code:
========VB client code========
Sub CallService()
Dim client As New CalcSVC.CalcServiceClient
client.Endpoint.Contract.Behaviors.Add( _
New VBContractBehavior("custom_name", "http://someplace.com") _
)
client.ClientCredentials.ClientCertificate.SetCertificate( _
StoreLocation.CurrentUser, _
StoreName.My, _
X509FindType.FindByThumbprint, _
"9f1bbe2bf87df0e4c021292ffd8c68ad08648b7c")
Using New OperationContextScope(client.InnerChannel)
OperationContext.Current.OutgoingMessageHeaders.Add( _
New MyCustomSoapHeader("test header") _
)
Dim returnValue As String = client.GetDescription()
Console.WriteLine(returnValue)
End Using
End Sub
======================================
and I include the app.config file below:
=======VB client App.config file============
<system.serviceModel>
<diagnostics>
<messageLogging logMalformedMessages="true"
logMessagesAtTransportLevel="true" />
</diagnostics>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ICalcService">
<security mode="Message">
<message clientCredentialType="Certificate"
negotiateServiceCredential="true"
algorithmSuite="Default"
establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:11111/CalcService"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_ICalcService"
contract="CalcSVC.ICalcService"
name="WSHttpBinding_ICalcService">
<identity>
<certificate encodedValue=".....[depend on the
server-side certificate].........." />
</identity>
</endpoint>
</client>
</system.serviceModel>
===================
when calling the service, you can use WCF message trace/log to view the
message sending/receving. Here is the outgoing message I captured, you can
see that the "custom_name" header is signed(with a u:Id ):
=====logged soap message=======
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1" u:Id="_2"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-
utility-1.0.xsd"
xmlns:a="http://www.w3.org/2005/08/addressing">GetDescription</a:Action>
<custom_name u:Id="_3" name="test header" xmlns="http://someplace.com"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-
utility-1.0.xsd"></custom_name>
...................
==============================
BTW, I've posted the detailed about securing a dynamic message header in
WCF on my blog. You can also have a look there.
http://blogs.msdn.com/stcheng/archive/2009/02/18/wcf-secure-a-dynamically-ad
ded-message-header-via-behavior-extension-part-1.aspx
http://blogs.msdn.com/stcheng/archive/2009/02/19/wcf-secure-a-dynamically-ad
ded-message-header-via-behavior-extension-part-2.aspx
If you still have anything unclear, please feel free to let me know.
Sincerely,
Steven Cheng
Microsoft MSDN Online Support Lead
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
msd...@microsoft.com.
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.
--------------------
>From: =?Utf-8?B?TWlrZSBMb2dhbg==?= <Mike...@community.nospam>
>References: <426857A0-B405-493C...@microsoft.com>
<8GA#BAAkJH...@TK2MSFTNGHUB02.phx.gbl>
<MDsNiQQk...@TK2MSFTNGHUB02.phx.gbl>
>Subject: RE: Sign custom SOAP Header on outbound call with WCF
>Date: Thu, 19 Feb 2009 03:54:01 -0800
I think I'm getting somewhere. I used your binding to start with. When
negotiateServiceCredential is "true" it sends the xml message below (ex. 1).
My broker has no clue what to do with it. So I set
negotiateServiceCredential to false. Then I get the error "The client
certificate is not provided. Specify a client certificate in Client
Credentials.". So I changed my client code to (ex. 2) and it still couldn't
find the cert. I made sure that COMPUTER/USERS had read access to the cert
using the WSE 3.0 Certificate tool. I also ensured the cert was in the
Trusted Cert. Authorities group. The cert is located in my Local Machine,
not Current User.
So I was playing around with the binding some more and I changed
clientCredentialType to None. I got this weird error about "Identity check
failed for outgoing message. The expected DNS identity of the remote
endpoint was 'mycompany.com' but the remote endpoint provided DNS claim
'mycert'. I looked up that error and added <identity> section in the client
section of the config file, see ex 3.
That sent a request to my web service broker, however it didn't understand
it still, and the custom soap header was gone, see ex 4. So I'm stuck with
the following binding and client endpoint in the app.config ex 5.
Again thanks for the help. As you can see I'm thoroughly confused.
Mike Logan
==========================
example 1
==========================
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action
s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
<a:MessageID>urn:uuid:1376a079-3df5-4df3-a3f4-047fd9bc6ecf</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To
s:mustUnderstand="1">http://mycompany.com/svcaddresslocation</a:To>
</s:Header>
<s:Body>
<t:RequestSecurityToken
Context="blah blah"
xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:KeySize>256</t:KeySize>
<t:BinaryExchange
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType=" http://schemas.xmlsoap.org/ws/2005/02/trust/tlsnego">blah
blah</t:BinaryExchange>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>
==========================
example 2
==========================
changed from this:
clientproxy.ClientCredentials.ClientCertificate.SetCertificate( _
"cn=mycert", _
System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, _
System.Security.Cryptography.X509Certificates.StoreName.My)
to this:
clientproxy.ClientCredentials.ServiceCertificate.SetDefaultCertificate( _
System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, _
System.Security.Cryptography.X509Certificates.StoreName.My, _
System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName,
_
"mycert")
I also tried cn=mycert there to. Still couldn't find the cert.
==========================
example 3
==========================
<endpoint address="http://mycompany.com/svcaddresslocation"
binding="wsHttpBinding" bindingConfiguration="MyBinding1"
contract="Service1Proxy.Service1Soap"
name="MyBinding1">
<identity>
<dns value="mlogansc1" />
</identity>
</endpoint>
==========================
example 4
==========================
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1"
u:Id="_4">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</a:Action>
<a:MessageID
u:Id="_5">urn:uuid:cb3e3e0a-a304-4566-be59-1f150c366f32</a:MessageID>
<a:ReplyTo u:Id="_6">
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1"
u:Id="_7">http://mycompany.com/svcaddresslocation</a:To>
<o:Security s:mustUnderstand="1"
xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="uuid-cc9549b3-8fb7-4da3-a848-b6292a842ae8-3">
<u:Created>2009-02-20T12:34:33.054Z</u:Created>
<u:Expires>2009-02-20T12:39:33.054Z</u:Expires>
</u:Timestamp>
<e:EncryptedKey
Id="uuid-cc9549b3-8fb7-4da3-a848-b6292a842ae8-2"
xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<DigestMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"
xmlns="http://www.w3.org/2000/09/xmldsig#"/>
</e:EncryptionMethod>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<o:SecurityTokenReference>
<o:KeyIdentifier
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1">f9oeOUyFG4RonLQRVm0G0yS68Vk=</o:KeyIdentifier>
</o:SecurityTokenReference>
</KeyInfo>
<e:CipherData>
<e:CipherValue>a long cipher value</e:CipherValue>
</e:CipherData>
</e:EncryptedKey>
<c:DerivedKeyToken u:Id="_0"
xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
<o:SecurityTokenReference>
<o:Reference
URI="#uuid-cc9549b3-8fb7-4da3-a848-b6292a842ae8-2"
ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey"/>
</o:SecurityTokenReference>
<c:Offset>0</c:Offset>
<c:Length>24</c:Length>
<c:Nonce>some security value</c:Nonce>
</c:DerivedKeyToken>
<c:DerivedKeyToken u:Id="_1"
xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
<o:SecurityTokenReference>
<o:Reference
URI="#uuid-cc9549b3-8fb7-4da3-a848-b6292a842ae8-2"
ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey"/>
</o:SecurityTokenReference>
<c:Nonce>some security value</c:Nonce>
</c:DerivedKeyToken>
<e:ReferenceList xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:DataReference URI="#_3"/>
<e:DataReference URI="#_8"/>
</e:ReferenceList>
<e:EncryptedData Id="_8"
Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<o:SecurityTokenReference>
<o:Reference URI="#_1"/>
</o:SecurityTokenReference>
</KeyInfo>
<e:CipherData>
<e:CipherValue>
some long cipher value
</e:CipherValue>
</e:CipherData>
</e:EncryptedData>
</o:Security>
</s:Header>
<s:Body u:Id="_2">
<e:EncryptedData Id="_3"
Type="http://www.w3.org/2001/04/xmlenc#Content"
xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<o:SecurityTokenReference
xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:Reference URI="#_1"/>
</o:SecurityTokenReference>
</KeyInfo>
<e:CipherData>
<e:CipherValue>some long cipher value</e:CipherValue>
</e:CipherData>
</e:EncryptedData>
</s:Body>
</s:Envelope>
my web service broker returned
SECU1037: Security Failure on Access Point 'MyService1'. Reason: SECU3766:
Encrypted elements detected but not specified by security contract.
==========================
example 5
==========================
<binding name="MyBinding1" useDefaultWebProxy="false">
<security mode="Message">
<message clientCredentialType="None" negotiateServiceCredential="false"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
<client>
<endpoint address="http://mycompany.com/svcaddresslocation"
binding="wsHttpBinding" bindingConfiguration="MyBinding1"
contract="Service1ClientProxy.Service1Soap"
name="MyBinding1">
<identity>
<dns value="mycert" />
</identity>
</endpoint>
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header>
<wsa:Action>http://www.somecompany.com/Service1/Operation1</wsa:Action>
<wsa:MessageID>urn:uuid:8ff585c9-60df-40fd-8453-edebcc170ee9</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://www.somecompany.com/Service1?WSDL</wsa:To>
<mycomp:CustomHeader wsu:Id="ID-0e743eb1-2ddf-407c-a588-129d072f5b3c"
xmlns:mycomp="http://www.somecompany.com">AppUser</mycomp:CustomHeader>
<wsse:Security
soap:actor="http://schemas.xmlsoap.org/soap/actor/next"
soap:mustUnderstand="1">
<wsu:Timestamp
wsu:Id="Timestamp-137e7a9a-2f9f-4abe-bb0a-d827719cf00a">
<wsu:Created>2009-02-23T11:00:18Z</wsu:Created>
<wsu:Expires>2009-02-23T11:05:18Z</wsu:Expires>
</wsu:Timestamp>
<wsse:BinarySecurityToken
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
wsu:Id="SecurityToken-140c2271-db42-41c8-adb4-4d3a4d548c9f"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">SOME LONG STRING WAS HERE</wsse:BinarySecurityToken>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<ds:CanonicalizationMethod
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<SignatureMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#ID-0e743eb1-2ddf-407c-a588-129d072f5b3c">
<Transforms>
<Transform
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>A DIGEST VALUE WAS HERE</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>SOEM LONG STRING WAS HERE</SignatureValue>
<KeyInfo>
<wsse:SecurityTokenReference>
<wsse:Reference
URI="#SecurityToken-140c2271-db42-41c8-adb4-4d3a4d548c9f"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
</wsse:SecurityTokenReference>
</KeyInfo>
</Signature>
</wsse:Security>
</soap:Header>
<soap:Body>
<Operation1 xmlns="http://www.somecompany.com/Service1">
<object1>hello there</object1>
</Operation1>
</soap:Body>
</soap:Envelope>
So I think the problem is also a bit specific to the ws-* secured
webservice you're calling. At your side, the WCF client generated the
proxy(and bindingsettings) according to the webservice(the service policy
in wsdl). Therefore, the test WCF service I used on my side(which simply
use a wshttpbinding with message security) will not quite conform to your
enviornment.
I'll need to perform more investigation on this. Is it possible for you to
give me a public internet address of the webservice for test? Also, if
convenient, would you start a new thread so that we can continue working on
this problem in the new thread?
Looking forward to your reply.
Sincerely,
Steven Cheng
Microsoft MSDN Online Support Lead
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
msd...@microsoft.com.
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.
--------------------
>From: =?Utf-8?B?TWlrZSBMb2dhbg==?= <Mike...@community.nospam>
>Subject: RE: Sign custom SOAP Header on outbound call with WCF
>Date: Fri, 20 Feb 2009 04:45:00 -0800