Web service different internal soap:address. How to call methods - c#

I am trying to call a web service method using c# and I get a response
There was no endpoint listening at https://sub.example.com/Service/Services.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
Inner exception as follows
The remote server returned an error: (404) Not Found.
I am thinking that this is because of proxy or some other issue. When I add the reference using Visual Studio it will auto generate soap address to
http://computername.local/Service/Service.svc
So the key problem is that service is available by different address externally but IIS responses are using internall address.
I have tried to call web service methods using different approaches binging connection to proxy address but it is no use. Is there a way to solve this or does the service provider need to make a change in the IIS configuration?
Config is as follows
<behaviors>
<serviceBehaviors>
<behavior name="ServiceLibrary.Service1Behavior">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceAuthorization principalPermissionMode="None" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBindingConfiguration" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
When accessing site using http the service returns either IP or name, same as in the address bar. But when accessing using https service returns computer name.

So it turns out that the bindings are the reason why this is not working
<binding name="BasicHttpBindingConfiguration" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
Security mode was wrong and it should be
security mode="Transport"
If there is need to have http and https side bu side then there is need to add multiple bindings.
How can I combine the WCF services config for both http and https in one web.config?

Related

httpBasicBinding with authentication and no message or transport security

I've got a small WCF service in intranet and I need to implement authentication in it. This service communicates with different Java clients over http (uses basicHttpBinding). I've tried to configure binding like so
<basicHttpBinding>
<binding>
<security mode="None">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
And added service behaviour
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="LocalTasks.Services.Validators.IntegrationUserNameValidator,LocalTasks.Services"/>
</serviceCredentials>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
But calls to this service do not hit my custom UserNamePassword validator.
I've also tried the same variant but with security mode set to Message and added a certificate. In this case validator worked fine.
How to configure service to authenticate users via basicHttpBinding without any message or transport security?
You cannot do that. You need either message or transport security, in order to have the credentials encrypted when they travel from the client to the server.
You really should use Message or Transport security.
You could also use TransportCredentialOnly, which will not require an SSL certificate, but that is recommended for testing only.
<basicHttpBinding>
<binding name="Authentication" >
<security mode="TransportCredentialOnly" >
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>

Getting current user from a basic WCF service project

I have a basic WCF service project in Visual Studio 2010, which consists of a .svc file, the associated .cs, and Web.config. My problem is that when using the WCF Test Client I can't get a user. OperationContext.Current.ServiceSecurityContext is null, as is HttpContext.Current. I managed to get security set to Transport on the WCF client, but now I'm getting the following error:
The provided URI scheme 'http' is invalid; expected 'https'.
My Web.config is as follows:
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
My WCF Test Client config is as follows:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_MyService">
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:57165/MyService.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_MyService" contract="MyService"
name="BasicHttpBinding_MyService" />
</client>
</system.serviceModel>
</configuration>
I'm totally new to writing new services, so the other posts I've seen that supposedly answer the question say to do things but not where to do them. I'm looking for something clear and concise here.
What am I missing here, or am I going about getting the current user all wrong?
The WCF client throws the "The provided URI scheme 'http' is invalid; expected 'https' " error because the basicHttpBinding specifies security mode="Transport"> but the endpoint address currently indicates a non-secure protocol (endpoint address="http://localhost:57165/MyService.svc". Update the endpoint address to match the binding's security to resolve the communication issue.
Once the transport error is resolved, you can then focus on the proper security binding and the code needed to extract the user information. In order to get the username, your binding will need to specify a client credential type of username. Your service can then access the user information by using System.ServiceModel.ServiceSecurityContext through the OperationContext.
The following links may be useful:
http://www.codemag.com/article/0611051
http://msdn.microsoft.com/en-us/library/ms731058%28v=vs.110%29.aspx
http://msdn.microsoft.com/en-us/library/system.servicemodel.servicesecuritycontext(v=vs.110).aspx
In order to get windows credentials out of your wcf webservice, your binding has to be a wsHttpBinding:
<wsHttpBinding>
<binding name="wsHttpBinding_MyService">
<security mode="TransportCredentialOnly" />
</binding>
</wsHttpBinding>
This is an example of a working security that transports the credentials.

Intranet - web to remote wcf CredentialCache.DefaultNetworkCredentials not working

I have a ASP.NET MVC intranet application hosted in IIS that added WCF service reference the WCF resides in another computer and also expect windows authentication.
In my web this code is working great:
proxy = new MyProxyClient("configurationName", "remoteAddress");
proxy.ClientCredentials.Windows.ClientCredential.UserName = "myUserName";
proxy.ClientCredentials.Windows.ClientCredential.Password = "MyPassword";
proxy.SomeMethod(); //work great
but if I want the credential not to be hardcoded like this I am using: CredentialCache.DefaultNetworkCredentials like this:
proxy = new MyProxyClient("configurationName", "remoteAddress");
proxy.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
proxy.SomeMethod(); //not working throw exception
the above code throw SecurityNegotiationException with message: The caller was not authenticated by the service.
and the inner exception is: The request for security token could not be satisfied because authentication failed.
How can I pass the credential of the current user to the WCF service without hardcoded user name and password?
If your organization uses regular Windows authentication (NTLM) you can't do what you want due to "one-hop" restriction: credentials passed from user's computer to your server use "one-hop" (from direct login to one external computer) and such credentials can't be used to authenticate other servers from the first one.
More information can be found using following search term:ntlm one hop,i.e. Why NTLM fails and Kerberos works.
Standard solution:
Kerberos (often requires significant effort to get approval to enable/configure)
Use some other form of authentication than Windows. Consider if OAuth is possible. Don't go basic auth.
Switch WCF service to claims based authentication.
If WCF service can it can trust caller to verify incoming credentials more approaches are possible:
Run code under particular account that signs in locally on server and have permissions to call the service. The easiest approach is what shown in your post, but storing domain passwords (or any passwords) in plain text is not secure. One can also run process account under special credentials that have access to the remote service and temporary revert impersonation after verifying user credentials.
You can also configure WCF service to require client certificate and use such certificate when calling the WCF service. This way WCF service can verify if caller is known.
In the web.config (client and server), in the <system.serviceModel> section add/modify a binding to look something like this:
<basicHttpBinding>
<binding name="MyBasicBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
And, add this to client side web.config <system.web> section:
<identity impersonate="true" />
<authentication mode="Windows" />
The two changes will make the end-user the current user of the web request which will then be sent in the WCF message.
The user can then be retrieved on the server side like this:
ServiceSecurityContext.Current.WindowsIdentity
Please make sure the following configuration is there in service web.config.
<system.serviceModel>
<services>
<service name="MyWcf.Service1" behaviorConfiguration="MySvcBehavior">
<endpoint address="" binding="wsHttpBinding" contract="MyWcf.IService1" bindingConfiguration="MyWsHttpBinding"></endpoint>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="MyWsHttpBinding">
<security mode="Message">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</wsHttpBinding>
<basicHttpBinding>
<binding name="MyBasicBinding">
<security mode="Message">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MySvcBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
And in your client configuration file following should be there.
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security>
<transport clientCredentialType="Windows" />
<message clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/MyWcf/Service1.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService1" contract="MyWCFService.IService1"
name="WSHttpBinding_IService1">
</endpoint>
</client>
</system.serviceModel>
I tried by passing System.Net.CredentialCache.DefaultNetworkCredentials using above configuration and working fine for me. If it's not working for you then put debug point on line which passing credential and watch that System.Net.CredentialCache.DefaultNetworkCredentials Domain, UserName & Password values are blank or not. If Blank then it should work.
I assume that if you're looking within your CredentialCache.DefaultNetworkCredentials attribut you won't see the credential information.
From Microsoft website : The authentication informations return by the DefaultNetworkCredentials property will be only available for NTLM, Negotiate or Kerberos authentication.
To get your credential you need to implement this authentication.
You can use it by using impersonation wihtin your intranet application.
Impersonation allow your intranet application to be executed by the user of this one.
More information here :http://technet.microsoft.com/en-us/library/cc961980.aspx

Add additional SSL behavior for WCF endpoint within Azure Web Role

Our azure web application already uses https port 443 with our site certificate, we have a WCF service within this webrole that has an https endpoint using our cert to authenticate (1-way ssl), this same service needs an additional https endpoint supporting 2-way auth using our cert and the third party's cert. We have uploaded the cert, updated the service definition file, and added an endpoint that we are hoping will work, but in testing we are getting the error: The SSL settings for the service 'SslRequireCert' does not match those of the IIS 'None'.
so the endpoint that does work is: https://environemnt.application.com/Services/Service.svc
the endpoint that generates the error: https://environment.application.com/Services/Service.svc/twa
The key requirement is that it is https, port 443, at the above new endpoint, without altering the SSL behavior of the rest of the role, I have seen entries to change the IIS configuration or use the role editor to add an Https Input endpoint, but as we already have an Https Input endpoint on port 443 using our site cert I don't want to alter/affect the whole role.
If it is helpful the service is a WCF Service which consumes an Mtom encoded soap 1.2 message
here are the new values that we have entered, what else do I need?
<behaviors>
<serviceBehaviors>
<behavior name="SSLServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="OneWayAuthEndpointBehavior">
</behavior>
<behavior name="TwoWayAuthEndpointBehavior">
<endpointDiscovery enabled="true"></endpointDiscovery>
<clientCredentials>
<clientCertificate findValue="thumprint..." storeLocation="LocalMachine" storeName="CertificateAuthority" x509FindType="FindByThumbprint" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="SSLServiceBehavior" name="Service">
<endpoint address="" behaviorConfiguration="OneWayAuthEndpointBehavior"binding="wsHttpBinding" bindingConfiguration="HttpsMtomOneWay" contract="ITestService" />
<endpoint address="twa" behaviorConfiguration="TwoWayAuthEndpointBehavior" binding="wsHttpBinding" bindingConfiguration="HttpsMtomTwoWay" contract="ITestService"/>
</services>
<bindings>
<wsHttpBinding>
<binding name="HttpsMtomOneWay" messageEncoding="Mtom">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
<binding name="HttpsMtomTwoWay" messageEncoding="Mtom">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
thank you much
Fixed through these steps:
Added serviceCredentials.serviceCertificate (cert details for our cert) to the service behavior
Eliminated Endpoint behavior definitions
Changed the HttpsMtomTwoWay binding to securityMode=Message
Now the message handlers handle the authentication exchange and external cert validation, then pass on to the transport endpoint, and we did not need to mess with the site wide SSL or endpoint settings. Tested and verified with numerous 3rd parties.

WCF Secured Using Membership Provider, but getting certificate error

I've created a custom membership provider and I am trying to use it to secure my WCF service. But, I am getting this error:
The service certificate is not provided. Specify a service certificate in ServiceCredentials.
I don't want to use an x509 certificate. How can I get this working?
Here is my service config:
<?xml version="1.0"?>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding1" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="UpdateService.UpdateService" behaviorConfiguration="ASPNETProviders">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding1"
contract="UpdateService.IUpdateService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ASPNETProviders">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="myUpdateMembershipProvider"/>
</serviceCredentials>
</behavior>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
UPDATE
This blog post, enter link description here, says:
[When] you opt in for the UserName client credential type, WCF insists that your service must also reference a service certificate that contains a private key.
I am going to host my service in IIS and plan to use SSL certificate in the web site for encrypting communication. Can I make WCF not insist that I reference a service certificate?
It seems that Microsoft really, really wants me to use a certificate.
Someone developed a Clear Username Binding for my situation, but I think I may just surrender and use a certificate.
Have you try to create a custom credential validator ? See this : http://nayyeri.net/custom-username-and-password-authentication-in-wcf-3-5

Categories

Resources