I have a WCF service which must be secured with Windows and Certificate authentication.
I know that wsHttpBinding does no support Streaming but according to msdn it can be done using transport security with a customBinding but I am not able to do it...
<customBinding>
<binding name="AuthBinding">
<mtomMessageEncoding maxBufferSize="65535" />
<windowsStreamSecurity protectionLevel="Sign"/>
<httpTransport transferMode="Streamed" maxReceivedMessageSize="2147483647" />
</binding>
</customBinding>
I am going from one exception to another :
The security capabilities of binding 'System.ServiceModel.Channels.CustomBinding' do not match those of the generated runtime object. Most likely this means the binding contains a StreamSecurityBindingElement, but lacks a TransportBindingElement that supports Stream Security
Or
The request message must be protected. This is required by an operation of the contract ('IEntity','WebService.Entity'). The protection must be provided by the binding ('CustomBinding','WebService.Entity')
Rather than being done in a single step, this is two step process.
Enable Transport Security with Certificate Authentication.
Enable Transport Security with Windows Authentication.
Also I am not sure both works together.
But MSDN Article found seems to direct in a correct direction:
How to: Secure a Service with Windows Credentials with wsHttpBinding
Please refer these links from MSDN for further learning (not much help if you are in hurry to deliver some milestone):
Transport Security with Windows Authentication
Transport Security with Certificate Authentication
Update
You have to use custom binding having Mixed (transport with message credentials) security mode.
Three binding elements relate to message level security, all of which derive from the SecurityBindingElement class.
The three are TransportSecurityBindingElement, SymmetricSecurityBindingElement, and AsymmetricSecurityBindingElement. The TransportSecurityBindingElement is used to provide Mixed mode security. The other two elements are used when the message layer provides security.
Additional classes are used when transport level security is provided:
HttpsTransportBindingElement
SslStreamSecurityBindingElement
WindowsStreamSecurityBindingElement
You can get help on:
How to: Create a Custom Binding Using the SecurityBindingElement
and
Security Capabilities with Custom Bindings
This works for me:
<basicHttpBinding>
<binding name="basic" transferMode="Streamed" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
Related
I have just put my webservice onto IIS 7 and I need to use basic authentication, I have set this up in IIS 7 by enabling it, however I am getting the common error:
the http request is unauthorized with client authentication scheme
'basic' the authentcation header received from the server was 'basic
realm' = "server address"
In my client I am using
binding.Security.Mode = ServiceModel.BasicHttpSecurityMode.TransportCredentialOnly
binding.Security.Transport.ClientCredentialType = ServiceModel.HttpClientCredentialType.Basic
With the same settings in the service
<basicHttpBinding>
<binding name="binding1">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
/binding>
</basicHttpBinding>
I see that a lot of solutions to this is to use a different security mode like transport which uses HTTPS and a certificate instead of HTTP. I dont want this, so is there anyway of solving this without HTTPS?
Thanks
I wish to provide security for a webservice. I initially used BasicHttpBinding with Transport security (ssl) and message security (to pass username and password for Custom Username Password Validation)...
But the consumers of the web service said they cant add a header to the soap message with security details.. and said they would like to pass it on the communication channel for the service.
Is it possible to do custom validation of user, with transport security with WCF?? I can't get it working :(
Any suggestions?
thanks
Neil
I think your consumers are asking for Basic Authentication. That is, where the authentication token is passed in the HTTP Authorization header rather than in the SOAP security header. Confidentiality of the credentials will be provided only by the transport (HTTPS).
The binding configuration for this is:
<basicHttpBinding>
<binding name="HTTPSwithBasicAuthentication">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
On the client, you set the credentials like this
serviceClient.ClientCredentials.UserName.UserName = "username";
serviceClient.ClientCredentials.UserName.Password = "password";
Assuming your service is hosted in IIS, remember to enable Basic Authentication in the IIS configuration.
To do the actual authorization of the users you will could implement a custom ServiceAuthorizationManager to contain your authorization logic. There are lots of examples of how to do that last part on the web.
Alternatively you could configure in a standard ASP.Net membership provider if that is appropriate for your application.
http://msdn.microsoft.com/en-us/library/bb398990(VS.100).aspx
I have a Silverlight 5 app that gets some data from a couple Sharepoint lists. It was all working correctly, then we set up the site to allow SSL and I tried to update the service reference to call the webservice using https. It updated the client config binding to use security mode Transport. But when it calls the service it's giving an error:
System.ServiceModel.CommunicationException: An error occurred while trying to make a request to URI 'https://devlpadmin.thelittlegym.com/_vti_bin/Lists.asmx'. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details. ---> System.Security.SecurityException ---> System.Security.SecurityException: Security error.
Does anyone know what the problem is or how to get more info than "Security error."?
I've gone through so many different combinations of things that I'm not sure exactly what has happened when, but it's now working. I think originally the site/service was having some weird problem that prompted me to try to manually configure Silverlight to pass NTLM transport credentials. In doing so, I might have created an invalid config file causing the error. The configuration that is working is:
<bindings>
<basicHttpBinding>
<binding name="ListsSoap" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://devadmin.mydomain.com/_vti_bin/Lists.asmx"
binding="basicHttpBinding" bindingConfiguration="ListsSoap"
contract="SPListsService.ListsSoap" name="ListsSoap" />
</client>
So if you're having this error and not making a cross-domain call, suspect some kind underlying service error. If you're not using Silverlight, you can enable tracing to track down the error. If you are using Silverlight, I still don't know what can be done to narrow it down, but be aware that Silverlight only supports a fragment of the configuration options that a normal .net WCF client does.
I'm trying to make a self hosted WCF app that uses nettcpbinding but works in an environment without a domain.
It's just two regular windows pc's, one is the server and the other one will be the client. The problem with this is that when I try to get the client to connect it's rejected because of the security settings.
Can you please point me in the right direction as to how I can get this scenario to work?
Should I (if possible) disable security?
Is there another (hopefully simple) way to accomplish this?
Regards,
Daniel
If you'd like to disable security for testing purposes, in the App.config of the WCF project, change the security element to <security mode="None" />, e.g.:
<bindings>
<netTcpBinding>
<binding name="netTcpBindingConfig" transferMode="Buffered" maxReceivedMessageSize="5242880">
<readerQuotas maxArrayLength="5242880" />
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
If you have a client, update the service reference to sync the security settings. Keep in mind that you should use some level of security in production environments.
I cannot figure out how to enable per-session instances for my WCF service while using HTTPS. (I'm not an ASP.NET expert but don't want to use ASP.NET session state if possible.) I am using .NET Framework 3.0.
I have arrived at the following contradiction and am hoping that someone can tell me where there is a flaw in the logic.
1) The service must be hosted on IIS 6 due to client mandate.
2) The service needs to maintain state between calls, including SqlConnection and SqlTransaction instances (ugly but necessary due to project constraints).
3) Therefore I need to use the wsHttpBinding.
4) The service needs to be able to access user authentication info from HttpContext.Current.User.Identity (e.g. using Windows security in IIS).
5) HTTPS is therefore required.
6) Transport-level security must therefore be configured on the binding.
7) Configuring the service to require sessions means I have to configure the wsHttpBinding to use Reliable Sessions.
8) This requires that message-level security is configured on the binding.
I.e. (6) and (8) are mutually exclusive.
It seems that using WCF sessions requires that I use message-level security, which prevents me from using HTTPS.
What am I missing?
3) True, wsHttpBinding and wsDualHttpBinding are the only HTTP bindings that support sessions
5) False, in order to authenticate the service callers you don't necessarily need to have any transport-level security (such as SSL/HTTPS). The only requirement is to configure IIS to enable Integrated Windows Authentication for a virtual directory. Then in WCF you have three possibilities to enable this scenario:
a) Use transport-level security on the wsHttpBinding with Windows credentials (HTTPS)
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="SecurityEnabledWsHttp">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
b) Use message-level security on the wsHttpBinding with Windows credentials (HTTP)
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="SecurityEnabledWsHttp">
<security mode="Message">
<message clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
c) Run your service under the ASP.NET Compatibility Mode and enable Windows Authentication in ASP.NET (HTTP)
<system.web>
<authentication mode="Windows" />
</system.web>
Note that in a and b you will access the identity of the caller from within a service this way:
OperationContext.Current.ServiceSecurityContext.WindowsIdentity
6) True, transport-level security must be enabled on the wsHttpBinding in order to use HTTPS
7) False, Reliable Sessions is a particular implementation of Reliable Messaging for WCF sessions. Reliable Messaging is a WS-* standard specification designed to guarantee message delivery on an unreliable network. You can use WCF sessions without Reliable Messaging, and viceversa. Sessions are enabled on the service contract with this attribute:
[ServiceContract(SessionMode=SessionMode.Required)]
public interface IMyService {
// ...
}
Also remember that in order to maintain state between service calls you will explicitly have to enable the appropriate instance mode on the service contract implementation:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class MyService : IMyService {
// ...
}
There are two kinds of sessions in WCF: Secure Sessions and Reliable Sessions. The default setting for both wsHttpBinding and netTcpBinding is to use Secure Sessions.For wsHttpBinding this is accomplished with message-level security by using the client's credentials, which is the default setting for the binding.For netTcpBinding instead, the session is established at the tranport level by using the facilities of the TCP protocol.
This means that simply switching to wsHttpBinding or netTcpBinding will enable support for WCF sessions.
The alternative is to use Reliable Sessions. This has to explicitly be enabled in the binding configuration, and removes the requirement of using message security for the wsHttpBinding. So this will work:
<bindings>
<wshttpbinding>
<binding name="ReliableSessionEnabled">
<reliablesession enabled="True" ordered="False" />
<security mode="None" />
</binding>
</wshttpbinding>
</bindings>
8) False, Reliable Sessions are used independently of the security settings of the communication channel.
For a more detailed explanation, have a look at this article.
Following through on Enrico's excellent answer, these are the configs I am using:
Service:
<services>
<service name="Foo.Bar.Service">
<endpoint name="EndpointHttps"
address=""
binding="customBinding" bindingConfiguration="EndpointHttps"
contract="Foo.Bar.IService" />
</service>
</services>
<bindings>
<customBinding>
<binding name="EndpointHttps">
<reliableSession />
<mtomMessageEncoding />
<httpsTransport />
</binding>
</customBinding>
</bindings>
Client:
<client>
<endpoint name="EndpointHttps"
address="https://server/FooBar/service.svc"
binding="customBinding" bindingConfiguration="EndpointHttps"
contract="Foo.Bar.IService" />
</client>
<bindings>
<customBinding>
<binding name="EndpointHttps">
<reliableSession />
<mtomMessageEncoding />
<httpsTransport />
</binding>
</customBinding>
</bindings>
Note: still haven't gotten this to work with Windows authentication though.