I'm trying to set up security on a WCF web service, using the ProtectionLevel attribute:
[ServiceContract(ProtectionLevel= ProtectionLevel.EncryptAndSign)]
This compiles, but Visual Studio throws exceptions when I try to update the service reference in another project (same solution).
System.InvalidOperationException: The
request message must be protected.
This is required by an operation of
the contract
('IStorageService','tempuri.org/';).
The protection must be provided by the
binding
('WSHttpBinding','tempuri.org/';).
What else do I need to set up to get this to work?
Your ServiceContract attribute is specifying that the service requires a secure channel for all operations, with both message signing (the message contains a digital signature which can prove that it hasn't been tampered with) and message encryption (the bytes of the message are encrypted when transmitted over the network).
Your client code (i.e. in the project which calls the service) must satisfy these requirements. If this project is using BasicHttpBinding with default settings, then the requirements of the service will not be satisfied (security is disabled by default for the BasicHttpBinding). If you configure the client project to use WsHttpBinding instead, with its default settings, the exception should go away (this binding has EncryptAndSign enabled by default).
The ProtectionLevel is a way for the developer to set the minimum level that a binding must comply with. When a service is deployed, the actual binding specified in configuration may or may not support the minimum level. For example, by default, the BasicHttpBinding class does not supply security (although it can be enabled). Therefore, using it with a contract that has any setting other than None will cause an exception to be thrown. see here
Related
The request message must be protected. This is required by an operation of the contract ('IMyNumericService','http://tempuri.org/'). The protection must be provided by the binding ('BasicHttpBinding','http://tempuri.org/').
when i am trying to connect to the host where i have registered my service , i am getting the above exception. But Host was working ,when i try to connect from client app it was showing above exception
On to client and service security in WCF. You can set the protection level of messages sent over the wire at the message, fault, operation and/or service level in WCF. There are three message ProtectionLevel property flavors to set as an attribute. This ensures that any endpoint used for the service will require this protection level as a minimum.
None
Plain text traveling over the wire.
Sign
The message is digitally signed.
Ensures no modification to the message.
The message is still plain text.
EncryptAndSign
Before signing, the message is encrypted.
Ensures no modification to the message and is scrambled.
If, for instance, the EchoService is set a ProtectionLevel of EncryptAndSign on the ServiceContract level, an endpoint with BasicHttpBinding would fail to start up. This is because BasicHttpBinding doesn’t support this protection level by default (it can be enabled).
[ServiceContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public interface IEchoService
{
[OperationContract(IsOneWay = true)]
void RegisterClient(Guid guid);
[FaultContract(typeof(EchoFault))]
[OperationContract]
EchoMessage Echo(EchoMessage message);
[OperationContract]
List<EchoMessage> GetAllEchos();
}
Using this protection level with a BasicHttpBinding endpoint results in an exception on the host.
System.InvalidOperationException: The request message must be protected. This is required by an operation of the contract [..]. The protection must be provided by the binding [..].
However if we change the endpoint binding to, for instance, wsHttpBinding, the service runs fine. This is because WsHttpBinding supports the EncryptAndSign protection level by default.
I have a WinForm app which uses WCF to call a WCF service. I am trying to troubleshoot an issue and need to look at the wcf trace file without any encryption. So I have WCF endpoint set to use BasicHttpBinding and my service contract is set for SessionMode = SessionMode.NotAllowed.
However I keep getting an error "Contract requires Session, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it".
I don't want to use sessions. Why does it think I want to use sessions?
OR how do I get the messages to go on the wire where I can see objects and their properties in clear text in the trace file?
BasicHttpBinding never uses session. There is something incorrectly configured in your code (or you didn't correctly update service reference). To see messages even if security is enabled use Message logging.
I have a WCF self-hosted as a Windows Service.
When I start the service (under the NETWORK_SERVICE account), I can consume the service from my ASP.NET application on a different server.
However, the business rules have changed. Now I need to run the service under my own account. I am able to stop the service, and start it again under my account. No problem there.
Until I try to consume the service from my ASP.NET application on the other service. I get:
A call to SSPI failed, see inner exception
I'm relatively certain there's something I need to do security wise to eliminate this error, being new to all this I just don't know what.
Any help is greatly appreciated.
Thanks,
Jason
Usually this is a sign of a missing or misconfigured SPN, which gets in the way when you're using windows authentication (at the transport or message level) and Kerberos is being negotiated.
Notice that how/when the error manifests itself might depend on the way the hostname (or IP address) of the service host is used in the URL used by the client, since WCF will try, by default, to deduce the right SPN to use based on the URL information, unless you explicitly override it by setting the endpoint identity.
So likely all you need to do is register an SPN (using setspn.exe) for your new service and make sure your client uses an appropriate identity.
There's some more extra information on how WCF uses service identities here, here and here.
I am developing a wcf service (basicHttpBinding) that should also be consumed by non .net clients (e.g. Java clients). But now I wonder how the client can define his client config file. Or is this file only needed for .net-clients? (I am thinking of configurations like maxReceivedMessageSize or maxItemsInObjectGraph for example).
Each development platform (call it as you want: SOAP stack, Framework, API) has its own way to configure communication. You don't need to bother with it. You just need to expose correct WSDL and client's developer will be responsible for configuring the client application based on his needs.
If you want to extend documentation of your service in WSDL you can use wsdl:documentation. WCF doesn't offer it by default but you can use this technology sample to extend WCF. You can use such documentation for example to describe that service operation can return large amount of data. Another approach to add wsdl:documentation is using WCF Extras.
From the sound of it, the client shouldn't have access to those configuration options. For instance, why should a client to the WCF service be able to specify the maxReceivedMessageSize?
What you probably want to do is define these configuration options on the server-side. If a client makes a call and there is a conflict with one of your options (i.e. the client exceeds maxReceivedMessageSize), you'll want to throw a SoapException back to the client.
If you want to let the client have access to the configuration settings before he or she sends a request, you can always implement a simple web service method that sends back the values.
I'm building some routing functionality between services. The original service and the service that does the routing have an identical configuration; both are using netTcpBinding with the following binding configuration:
netTcpBinding
security mode="Message"
message clientCredentialType="UserName"
The service behavior uses a AspNet Membership Provider and a client certificate we've installed on the machine.
When I switch off the message security it relays just fine but when it's switched on I get the following exception:
"The message could not be processed. This is most likely because the action 'http://foo/Whatever' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings*. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding." (Emphasis mine)
My thinking is that the certificate is operating on the message twice (once on the original call and then on the relay) and this is what corrupts the message's security token.
Questions:
Is my thinking on target?
Is there a way to continue to use message security for routing without having the complexity of a token service?
You mentioned switching between no security and message security. Are you making sure to change both the WCF service endpoints as well as the endpoint on the receiving end? If not, and the two do not match up, you will receive an error. That's what that error seems to be saying to me.
For Question 2, what type of environment are you running in? A closed system where you could use encrypt and sign, or a public environment, where you might need to be using a special key?