.NET Framework Bookmark and Share   
 index > Windows Communication Foundation > Consume WCF service on SSL
 

Consume WCF service on SSL

Hi,

I know this question has been made before - but in a different form, so I didn't find the answer.

I want to connect to a WCF service, which is placed under https. I tried what I read from this article here (http://timheuer.com/blog/archive/2008/10/14/calling-secure-services-with-silverlight-2-ssl-https.aspx) - and modifiying ClientAccessPolicy.xml, so it now has:

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="SOAPAction">
        <domain uri="http://*"/>
        <domain uri="https://*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>
According to the article mentioned, this is enough.

Let me also post how I bind from Web.Config

<service behaviorConfiguration="KOM1secured.UserServicesBehavior"
    name="KOM1secured.UserServices">
    <endpoint address="" binding="basicHttpBinding" contract="KOM1secured.IUserServices"/>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
To consume the services from a different application, I do this:

BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://1.2.3.4/UserServices.svc");
 IUserServices userServices = new ChannelFactory<IUserServices>(basicHttpBinding, endpointAddress).CreateChannel();
- where 1.2.3.4 is the IP of the service. It throws back a 403, saying that I'm not allowed to connect - which makes sense, because I wrote http and not https. However, putting in https gives me: "System.ArgumentException: The provided URI scheme 'https' is invalid; expected 'http'.".

Any ideas on how to get to this service?

Thanks!


Anders V
You need to specify the security requirements for the binding as BasicHttpBinding defaults to unsecured

create a bindings section as follows under teh system.serviceModel element

<bindings>
<basicHttpBinding>
<binding name = "sec">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
<basicHttpBinding>
</bindings>

and then in your endpoint include a bindingConfiguration atttribute pointing to the "sec" binding section
Richard Blewett, thinktecture - http://www.dotnetconsult.co.uk/weblog2
Twitter: richardblewett
Richard Blewett
Thanks a lot for the quick answer.

I added the binding configuration on the service side - and the included the bindingConfiguration attribute, so on the service side it no looks like this:

<service behaviorConfiguration="KOM1secured.UserServicesBehavior"
name="KOM1secured.UserServices">
<endpoint address="" bindingConfiguration="sec" binding="basicHttpBinding" contract="KOM1secured.IUserServices"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>

However, if I test the client and have https in the endPointAddress' code, I get told that it expects 'http' - and if I put http, it tells me that: "System.ServiceModel.Security.MessageSecurityException: The HTTP request was forbidden with client authentication scheme 'Anonymous'. ---> System.Net.WebException: The remote server returned an error: (403) Forbidden."

I assume that it should be https in the endPointAddress - like this:

EndpointAddress endpointAddress = new EndpointAddress("https://1.2.3.4/UserServices.svc");

- but why does it come up with the message of "System.ArgumentException: The provided URI scheme 'https' is invalid; expected 'http'."

What's the missing piece?

++++++++++++++++++

PS: the rest of the exception when using https is:

Parameter name: via at System.ServiceModel.Channels.TransportChannelFactory`1.ValidateScheme(Uri via) at System.ServiceModel.Channels.HttpChannelFactory.ValidateCreateChannelParameters(EndpointAddress remoteAddress, Uri via) at System.ServiceModel.Channels.HttpChannelFactory.OnCreateChannel(EndpointAddress remoteAddress, Uri via) at System.ServiceModel.Channels.ChannelFactoryBase`1.InternalCreateChannel(EndpointAddress address, Uri via) at System.ServiceModel.Channels.ChannelFactoryBase`1.CreateChannel(EndpointAddress address, Uri via) at System.ServiceModel.Channels.ServiceChannelFactory.ServiceChannelFactoryOverRequest.CreateInnerChannelBinder(EndpointAddress to, Uri via) at System.ServiceModel.Channels.ServiceChannelFactory.CreateServiceChannel(EndpointAddress address, Uri via) at System.ServiceModel.Channels.ServiceChannelFactory.CreateChannel(Type channelType, EndpointAddress address, Uri via) at System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress address, Uri via) at System.ServiceModel.ChannelFactory`1.CreateChannel()
Anders V
Do you have metadata being served over http (httpGetEnabled=true in your serviceMetadataBehavior)? If so its still expecting to be able to use http - either add an http base address as well or change the behavior to use httpsGetEnabled = true
Richard Blewett, thinktecture - http://www.dotnetconsult.co.uk/weblog2
Twitter: richardblewett
Richard Blewett

Yes, I have httpsGetEnabled=true.

On the service side:

  <behaviors>
   <serviceBehaviors>
    <behavior name="SecuredBehaviour">
     <serviceMetadata httpsGetEnabled="true" />
    </behavior>
   </serviceBehaviors>
  </behaviors>
  
  <services>
   <service behaviorConfiguration="SecuredBehaviour" 
            name="KOM1secured.UserServices">
    <endpoint address="" 
              binding="basicHttpBinding"
              bindingConfiguration="SecuredBinding" 
              name="UserServices.Http" 
              contract="KOM1secured.IUserServices" />
     <endpoint address="mex" 
               binding="mexHttpBinding" 
               contract="IMetadataExchange" />
   </service>
  </services>
    
  <bindings>
   <basicHttpBinding>
     <binding name="SecuredBinding">
       <security mode="Transport">
         <transport clientCredentialType="None"/>
       </security>
     </binding>
   </basicHttpBinding>
  </bindings>

If I run this on the client:

            BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
            EndpointAddress endpointAddress = new EndpointAddress("https://1.2.3.4/UserServices.svc");
            IUserServices userServices = new ChannelFactory<IUserServices>(basicHttpBinding, endpointAddress).CreateChannel();


I get the message about expecting http and not https. I then tried to change the Web.Config on the client side, adding this:

    <bindings>
      <basicHttpBinding>
        <binding name="UserServices.Http">
          <security mode="Transport">
            <transport clientCredentialType="None"
                proxyCredentialType="None"
                realm="" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>

    <client>
      <endpoint address="https://1.2.3.4/UserServices.svc"
        binding="basicHttpBinding"
        bindingConfiguration="UserServices.Http"
        contract="KOM1secured.Client.IUserServices"
        name="UserServices.Http" />
    </client>

- and then changing the binding declaration to HttpBinding httpBinding = new HttpBinding("UserServices.http") ...but from that I get the error shown in the bottom of this.

Tough! Any ideas?

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

System.ServiceModel.ProtocolException: The content type text/html; charset=utf-8 of the response message does not match the content type of the binding (text/xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 1024 bytes of the response were: '

&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;



&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;&lt;title&gt;

&lt;/title&gt;&lt;link href=&quot;StyleSheet.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;

	&lt;style type=&quot;text/css&quot;&gt;
&lt;/style&gt;

&lt;/head&gt;
&lt;body&gt;
    &lt;form name=&quot;aspnetForm&quot; method=&quot;post&quot; action=&quot;login.aspx?ReturnUrl=%2fUserServices.svc&quot; id=&quot;aspnetForm&quot;&gt;
&lt;input type=&quot;hidden&quot; name=&quot;__VIEWSTATE&quot; id=&quot;__VIEWSTATE&quot; value=&quot;/wEPDwUJNjI0NjkyNzcyZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WAwUQY3RsMDAkaW1nQnRuTG9nbwUrY3RsMDAkQ29udGVudFBsYWNlSG9sZGVyNCRMb2dpbjEkUmVtZW1iZXJNZQUxY3RsMDAkQ29udGVudFBsYWNlSG9sZGVyNCRMb2dpbjEkTG9naW5JbWFnZUJ1dHRvbrGiS5hvsUnIQF/fmQ1auH4P9Tpa&quot; /&gt;

&lt;input type=&quot;hidden&quot; name=&quot;__EVENTVALIDATION&quot; id=&quot;__EVENTVALIDATION&quot; value=&quot;/wEWCgK6sKK+AwLQ7uz5DAK97MusCQK1suXbDgKstd38AQLN5o2oCQL63fDxDQLh97PgDgKAjNJ7AseCl44FP/qmqhoQ/hjQLZHyTaAa3EL7U88=&quot; /&gt;
    &lt;div class=&quot;header&quot;&gt;
           &lt;div class=&quot;headerLogo&quot;&gt;
			   &lt;input'.

Server stack trace: 
   at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory factory, WebException responseException, ChannelBinding channelBinding)
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at KOM1secured.IUserServices.CreateUserASP(String _username, String _password, String _email)
   at KOM1_web_services.GeneralData.CreateUserASP() in C:\Users\Anders\Documents\Visual Studio 2008\Projects\kom1 (2)\KOM1 web services\App_Code\GeneralData.cs:line 26
   at KOM1_web_services.UserControl.CreateUserASP() in C:\Users\Anders\Documents\Visual Studio 2008\Projects\kom1 (2)\KOM1 web services\UserControl.asmx.cs:line 50
Anders V
Correct, and the mex binding should be mexHttpsBinding also, the current one use mexHttpBinding.
Christopher Scrosati, Software Design Engineer, WCF Silverlight, Microsoft Corp.
Christopher Scrosati - MSFT
I believe we get a bit closer every time!

I added the (obvious) s in mexHttpsBinding, but I still get the same results as in the above.

Any more bits of erros? please...
Anders V
Actually, you can talk with the service now.It seems that you are getting a different error now.

I looked again at your latest post and you get an exception from the service. You should look into this.
Christopher Scrosati, Software Design Engineer, WCF Silverlight, Microsoft Corp.
Christopher Scrosati - MSFT
I use this to connect to the service:

BasicHttpBinding basicHttpBinding = new BasicHttpBinding("UserServices.Http");

EndpointAddress endpointAddress = new EndpointAddress("https://1.2.3.4/UserServices.svc");

IUserServices userServices = new ChannelFactory<IUserServices>(basicHttpBinding, endpointAddress).CreateChannel();


And then I made a service that does nothing but returning 'true' - but I still get that big error that I showed in the bottom a couple of posts up from here. If I go to the actual server where the service is hosted, I can navigate to https://1.2.3.4/UserServices.svc and see the service. However - and here comes a question - I have to log in to come to the https://1.2.3.4/UserServices.svc, because this web site uses the ASP.NET Membership Provider for protection; isn't that a problem? Or do the endpoints take care of this so that the login is bypassed somehow?

Thanks a lot for your help and patience!
Anders V

You can use google to search for other answers

Custom Search

More Threads

• wsHttpBinding: Changing from SymmetricBinding to AsymmetricBinding?
• Multiple callbacks with a call
• create unlimited client connections in polling duplex wcf service?
• Killing the wcf process.
• Multiple EndPoint
• How to increase Size of data Transfer in WCF?
• Using multiple client credentials
• Trying to serialize a class of classes
• Increasing data security in WCF.
• Is "Partial" Deserialization Possible with the XMLSerializer