I'd like to authenticate a user using ADFS 2.0 to use a self-written WCF service. The service is ready and fully functional. Also the ADFS 2.0 is set up correctly.
When I set up the client binding in code and do the stuff there, everything works as expected. But when I like to use the configuration generated by "update service reference", the binding is wrong and doesn't work as expected.
Where am I missing something? Any hints welcome.
Error given
Unhandled Exception: System.ServiceModel.FaultException: The message
with Action
'http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue' cannot be
processed at the receiver, due to a ContractFilter mismatch at the
EndpointDispatcher. This may be because of either a contract mismatch
(mismatched Actions between sender and receiver) or a binding/security
mismatch between the sender and the receiver. Check that sender and
receiver have the same contract and the same binding (including
security requirements, e.g. Message, Transport, None).
Server config:
<bindings>
<ws2007FederationHttpBinding>
<binding>
<security mode="TransportWithMessageCredential">
<message establishSecurityContext="false">
<issuerMetadata address="https://sts.local.domain/adfs/services/trust/mex" />
<issuer address="https://sts.local.domain/adfs/services/trust/2005/windowstransport" binding="ws2007HttpBinding" />
<claimTypeRequirements>
<add claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" isOptional="true" />
<add claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" isOptional="true" />
</claimTypeRequirements>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
<ws2007HttpBinding>
<binding>
<security mode="Transport">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>
<message clientCredentialType="None" establishSecurityContext="false" negotiateServiceCredential="true" />
</security>
</binding>
</ws2007HttpBinding>
</bindings>
Client config (not working):
<bindings>
<ws2007FederationHttpBinding>
<binding name="WS2007FederationHttpBinding_IMyService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="TransportWithMessageCredential">
<message algorithmSuite="Default" establishSecurityContext="false"
issuedKeyType="SymmetricKey" negotiateServiceCredential="true">
<issuer address="https://sts.local.domain/adfs/services/trust/2005/windowstransport" binding="ws2007HttpBinding" />
<issuerMetadata address="https://sts.local.domain/adfs/services/trust/mex" />
<tokenRequestParameters>
<AppliesTo xmlns="http://schemas.xmlsoap.org/ws/2004/09/policy">
<EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
<Address>https://service.machine.local/STSWcfService/MyService.svc</Address>
</EndpointReference>
</AppliesTo>
<trust:SecondaryParameters xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<trust:KeyType xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey</trust:KeyType>
<trust:KeySize xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">256</trust:KeySize>
<trust:Claims Dialect="http://schemas.xmlsoap.org/ws/2005/05/identity"
xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<wsid:ClaimType Uri="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
Optional="true" xmlns:wsid="http://schemas.xmlsoap.org/ws/2005/05/identity" />
<wsid:ClaimType Uri="http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
Optional="true" xmlns:wsid="http://schemas.xmlsoap.org/ws/2005/05/identity" />
</trust:Claims>
<trust:KeyWrapAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p</trust:KeyWrapAlgorithm>
<trust:EncryptWith xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptWith>
<trust:SignWith xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2000/09/xmldsig#hmac-sha1</trust:SignWith>
<trust:CanonicalizationAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/10/xml-exc-c14n#</trust:CanonicalizationAlgorithm>
<trust:EncryptionAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptionAlgorithm>
</trust:SecondaryParameters>
</tokenRequestParameters>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
<ws2007HttpBinding>
<binding>
<security mode="Transport">
<transport clientCredentialType="Windows" />
<message clientCredentialType="Windows" establishSecurityContext="false" />
</security>
</binding>
</ws2007HttpBinding>
</bindings>
<client>
<endpoint address="https://service.machine.local/STSWcfService/MyService.svc"
binding="ws2007FederationHttpBinding" bindingConfiguration="WS2007FederationHttpBinding_IMyService"
contract="ServiceReference.IMyService" name="WS2007FederationHttpBinding_IMyService" />
</client>
Client binding in code (working):
private static SecurityToken GetToken()
{
var factory = new WSTrustChannelFactory(new WindowsWSTrustBinding(SecurityMode.Transport), adfsEndPoint)
{
TrustVersion = TrustVersion.WSTrustFeb2005
};
var requestSecurityToken = new RequestSecurityToken
{
RequestType = WSTrustFeb2005Constants.RequestTypes.Issue,
AppliesTo = new EndpointAddress(serviceEndPoint),
KeyType = WSTrustFeb2005Constants.KeyTypes.Symmetric
};
var channel = factory.CreateChannel();
return channel.Issue(requestSecurityToken);
}
private static void CallService(SecurityToken token)
{
// create binding and turn off sessions
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.EstablishSecurityContext = false;
// create factory and enable WIF plumbing
var factory = new ChannelFactory<IMyService>(binding, new EndpointAddress(serviceEndPoint));
factory.ConfigureChannelFactory();
// turn off CardSpace - we already have the token
factory.Credentials.SupportInteractive = false;
var channel = factory.CreateChannelWithIssuedToken(token);
foreach (var claim in channel.GetClaims())
{
Console.WriteLine("{0}\n {1}\n {2} ({3})\n", claim.ClaimType, claim.Value, claim.Issuer, claim.OriginalIssuer);
}
}
I think that your security mode and client credentials might not be matching.
Put this in your app.config (client and server) and make sure that the processes have write access to the directory.
<system.diagnostics>
<sources>
<source name="Microsoft.IdentityModel" switchValue="Verbose">
<listeners>
<add name="xml" type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\temp\WIF.svclog" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="Verbose">
<listeners>
<add name="xml" type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\temp\WCF.svclog" />
</listeners>
</source>
</sources>
<trace autoflush="true" />
</system.diagnostics>
This helped me a lot when trying to figure out what's wrong. I also suggest (only for testing) to include service exception in your faults.
<behaviors>
<serviceBehaviors>
<behavior>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
Please do this and update your question with the errors from the log.
You can create another binding section and give it another name than the one generated by Visual Studio. On a next update, the bindings will be merged.
I can't add comments for some reason - however I have seen WCF 'ignore' my wshttpbinding and take a basichttpbinding instead when I've altered my SVC file contents - it ends up relying on the scheme to determine the binding and as a result, ignores anything except basicHttpBinding for a http address.
Have a look there and see if that helps.
Related
I am trying to consume a WCF service in my console app.
My App.Config file looks like this
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_InventItemGroupService" />
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://mydomain.com/MicrosoftDynamicsAXAif50/inventitemgroupservice.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_InventItemGroupService"
contract="ServiceReference1.InventItemGroupService" name="WSHttpBinding_InventItemGroupService">
<identity>
<userPrincipalName value="asd#as" />
</identity>
</endpoint>
</client>
</system.serviceModel>
Console app code to make authentication part.
protected ProgramClass(AifSos.InventItemGroupServiceClient inventItemGroupServiceClient) // Constructor
{
MInventItemGroupServiceClient = inventItemGroupServiceClient;
// ReSharper disable once PossibleNullReferenceException
MInventItemGroupServiceClient.ClientCredentials.Windows.ClientCredential.UserName = "un";
MInventItemGroupServiceClient.ClientCredentials.Windows.ClientCredential.Password = "pw";
MInventItemGroupServiceClient.ClientCredentials.Windows.ClientCredential.Domain = "domain";
}
All seems okay for me, But it always throws an error
The caller was not authenticated by the service.
Can any one point out what I am missing?
1 Go to your Client Project Properties.
a. Go to services tab
Enable this settings and use authentication mode windows
2 change app.config file inside client project with this two sample line
<security mode="None">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="false" algorithmSuite="Default" establishSecurityContext="false" />
</security>
3 change app.config file inside service project
<security mode="None">
<message clientCredentialType="Windows" negotiateServiceCredential="false" algorithmSuite="Default" establishSecurityContext="false" />
</security>
4 in client code when you creating service instance and calling for a service use this line to provide login info in service pc.
Service1Client client = new Service1Client();
client.ClientCredentials.Windows.ClientCredential.UserName = "ETLIT-1";
client.ClientCredentials.Windows.ClientCredential.Password = "etl";
client.ClientCredentials.Windows.AllowNtlm = false;
client.ClientCredentials.Windows.ClientCredential.Domain = "ETLIT-1-PC";
Console.WriteLine(client.addNumber(23, 2));
I hit the following error:
The request failed with HTTP status 401: Unauthorized.
The Code
The code is as follows:
protected void Execute_Click(object sender, EventArgs e)
{
/*Declare and initialize a variable for the Lists Web service.*/
//Web_Reference.Lists myservice = new Web_Reference.Lists();
ListsWebService.Lists myservice = new ListsWebService.Lists();
/*Authenticate the current user by passing their default
credentials to the Web service from the system credential
cache. */
myservice.Credentials =
System.Net.CredentialCache.DefaultCredentials;
/*Set the Url property of the service for the path to a subsite. Not setting this property will return the lists in the root Web site.*/
//listService.Url = "http://Server_Name/Subsite_Name/_vti_bin/Lists.asmx";
myservice.Url = "http://teamsites.ntu.edu.sg/sce/hrdev/_vti_bin/Lists.asmx";
try
{
/*Declare an XmlNode object and initialize it with the XML
response from the GetListCollection method. */
System.Xml.XmlNode node = myservice.GetListCollection();
/*Loop through XML response and parse out the value of the
Title attribute for each list. */
foreach (System.Xml.XmlNode xmlnode in node)
{
Label1.Text += xmlnode.Attributes["Title"].Value + "\n";
}
}
catch (Exception excep)
{
Label1.Text = excep.Message;
}
}
IIS Settings - Only Windows Authentication is Enabled.
Web.Config file
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=bxxxxxxxx9" >
<section name="ReadSharePointList.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=bxxxxxxxx9" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ListsSoap" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://mainsite/subsite/_vti_bin/lists.asmx"
binding="basicHttpBinding" bindingConfiguration="ListsSoap"
contract="StaffRole.ListsSoap" name="ListsSoap" />
</client>
</system.serviceModel>
<applicationSettings>
<ReadSharePointList.Properties.Settings>
<setting name="ReadSharePointList_ListsWebService_Lists" serializeAs="String">
<value>http://mainsite/subsite/_vti_bin/lists.asmx</value>
</setting>
</ReadSharePointList.Properties.Settings>
</applicationSettings>
</configuration>
Where could I be missing?
As you have only "Windows authentication" enabled on server side, try changing the config as below:
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" proxyCredentialType="None"
realm="" />
Is your C# ASP.NET running on the same physical server as SharePoint?
If so then its a good chance its the "Local Loopback Check"
If your ASP.Net page is in the same intranet you can use the System.Net.CredentialCache approach. See Reference: http://msdn.microsoft.com/en-us/library/hh134614(v=office.14).aspx
If your ASP.Net page is not hosted in the same intranet, you need to get past the authentication provider of the Sharepoint site. See Reference: http://msdn.microsoft.com/en-us/library/hh147177(v=office.14).aspx
I am able to connect to my WCF service with the Win-form application, however i am not able to do so with my windows service. Whenever i fire open() to the proxy it throws the following error
The server has rejected the client credentials
Inner Exception: System.Security.Authentication.InvalidCredentialException: The server
has rejected the client credentials.
---> System.ComponentModel.Win32Exception: The logon attempt failed
--- End of inner exception stack trace ---
at System.Net.Security.NegoState.ProcessAuthentication(LazyAsyncResult
lazyResult)
at System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential
credential, ChannelBinding binding, String targetName, ProtectionLevel
requiredProtectionLevel, TokenImpersonationLevel
allowedImpersonationLevel)
at System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential
credential, String targetName, ProtectionLevel
requiredProtectionLevel, TokenImpersonationLevel
allowedImpersonationLevel)
at System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream
stream, SecurityMessageProperty& remoteSecurity)
Tried searching for the solution, but none fitting my requirements, hence posted.
Please help...
Update 1:
#A.R., Tried using
client.ClientCredentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
but to no avail.
Update 2:
WCF service Configuration
<system.serviceModel>
<diagnostics performanceCounters="All" />
<bindings>
<netTcpBinding>
<binding name="myBindingForLargeData" maxReceivedMessageSize="5242880" maxConnections="10">
<readerQuotas maxDepth="64" maxStringContentLength="5242880" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
</binding>
</netTcpBinding>
</bindings>
<services>
<service behaviorConfiguration="WCFService.ServiceBehavior"
name="WCFService.CollectorService">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="myBindingForLargeData"
name="netTcpEndPoint" contract="WCFService.ICollectorService" />
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
name="mexTcpEndPoint" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8010/WCFService.CollectorService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFService.ServiceBehavior">
<serviceMetadata httpGetEnabled="False"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceThrottling
maxConcurrentCalls="32"
maxConcurrentSessions="32"
maxConcurrentInstances="32"
/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Thanks for all your help. i got the answer after few days of some research and trial n error method :) well i know i am late to post the answer, but i think its better late than never.
So Here's the solution
i had to make some changes in my configuration files (both client & server)
On the client side i added <security> tag as shown below
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTcpEndPoint" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="5242880" maxBufferSize="5242880" maxConnections="15" maxReceivedMessageSize="5242880">
<readerQuotas maxDepth="32" maxStringContentLength="5242880" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://xx.xx.xx.xx:8010/WCFService.CollectorService/" binding="netTcpBinding" bindingConfiguration="netTcpEndPoint" contract="CloudAdapter.CloudCollectorService.ICollectorService" name="netTcpEndPoint">
</endpoint>
</client>
</system.serviceModel>
and also added the same tag on the server side (WCF service configuration), as shown below
<bindings>
<netTcpBinding>
<binding name="myBindingForLargeData" maxReceivedMessageSize="5242880" maxConnections="10">
<readerQuotas maxDepth="64" maxStringContentLength="5242880" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
Hope this help a person in need :)
So the KEY is to make the <security> tag same over the client and the server configuration files.
Basically what is happening is that your calling service doesn't have the appropriate credentials, like you would have when calling from WinForms. What you need is some impersonation. It takes a bit of setting up, and is kind of annoying, but it will work.
Luckily MSDN has a nice little walkthrough.
http://msdn.microsoft.com/en-us/library/ms731090.aspx
There is some more general information on the topic here:
http://msdn.microsoft.com/en-us/library/ms730088.aspx
UPDATE:
Setting impersonation flags is not enough. You have to actually impersonate a credential to make it work. For example:
// Let's assume that this code is run inside of the calling service.
var winIdentity = ServiceSecurityContext.Current.WindowsIdentity;
using (var impContext = winIdentity.Impersonate())
{
// So this would be the service call that is failing otherwise.
return MyService.MyServiceCall();
}
Check out my answer on this post The server has rejected the client credentials.
Note the security node.
<bindings>
<netTcpBinding>
<binding name="customTcpBinding" maxReceivedMessageSize="20480000" transferMode="Streamed" >
<security mode="None"></security>
</binding>
</netTcpBinding>
</bindings>
What is the authentication mode you are using on your WCF Service? Seems like the winform app is running and providing the correct credentials while your windows service is not running with the specified privileges or the credentials being passed are not valid. Try to inspect your request using Fiddler when made from you winforms vs Windwos service and see the difference.
For me it helped to set on both sides (client + server) the security mode to None:
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
(Same answer as from spinner_den_g but in C# - no need to edit the app.config)
I'm trying to start with Adaptive Payments by Paypal using SOAP interface.
When adding service reference to https://svcs.sandbox.paypal.com/AdaptivePayments?WSDL the following warning is shown by Visual Studio:
Custom tool warning: Cannot import wsdl:binding
Detail: The WSDL binding named AdaptivePaymentsSOAP11Binding is not valid because no match for operation CancelPreapproval was found in the corresponding portType definition.
XPath to Error Source: //wsdl:definitions[#targetNamespace='http://svcs.paypal.com/services']/wsdl:binding[#name='AdaptivePaymentsSOAP11Binding'] C:\cproj\daemon\Service References\PaypalSandboxApi\Reference.svcmap 1 1 daemon
Discarding this message, the reference added successfully.
In order to perform a transaction, I try to create the client:
var client = new PaypalSandboxApi.AdaptivePaymentsPortTypeClient()
This throws InvalidOperationException:
Could not find default endpoint element that references contract 'PaypalSandboxApi.AdaptivePaymentsPortType' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
Am I missing something?
Should I use missing AdaptivePaymentsSOAP11Binding and not AdaptivePaymentsPortTypeClient?
It looks like importing this WSDL doesn't generate the servicemodel config. I kludged one together like this (and updated the relevant classname to match yours, so you can copy/paste):
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="PaypalAdaptivePayBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="1048576" maxBufferPoolSize="1048576" maxReceivedMessageSize="1048576" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="65536" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://svcs.sandbox.paypal.com/AdaptivePayments"
binding="basicHttpBinding" bindingConfiguration="PaypalAdaptivePayBinding"
contract="PaypalSandboxApi.AdaptivePaymentsPortType"
name="PaypalAdaptivePay" />
</client>
I am trying to make a WCF service over basicHttpBinding to be used over https. Here's my web.config:
<!-- language: xml -->
<service behaviorConfiguration="MyServices.PingResultServiceBehavior"
name="MyServices.PingResultService">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="defaultBasicHttpBinding"
contract="MyServices.IPingResultService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
...
<bindings>
<basicHttpBinding>
<binding name="defaultBasicHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
...
<behaviors>
<serviceBehaviors>
<behavior name="MyServices.UpdateServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
I am connecting using WCFStorm which is able to retrieve all the meta data properly, but when I call the actual method I get:
The provided URI scheme 'https' is invalid; expected 'http'. Parameter
name: via
Try adding message credentials on your app.config like:
<bindings>
<basicHttpBinding>
<binding name="defaultBasicHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
Adding this as an answer, just since you can't do much fancy formatting in comments.
I had the same issue, except I was creating and binding my web service client entirely in code.
Reason is the DLL was being uploaded into a system, which prohibited the use of config files.
Here is the code as it needed to be updated to communicate over SSL...
Public Function GetWebserviceClient() As WebWorker.workerSoapClient
Dim binding = New BasicHttpBinding()
binding.Name = "WebWorkerSoap"
binding.CloseTimeout = TimeSpan.FromMinutes(1)
binding.OpenTimeout = TimeSpan.FromMinutes(1)
binding.ReceiveTimeout = TimeSpan.FromMinutes(10)
binding.SendTimeout = TimeSpan.FromMinutes(1)
'// HERE'S THE IMPORTANT BIT FOR SSL
binding.Security.Mode = BasicHttpSecurityMode.Transport
Dim endpoint = New EndpointAddress("https://myurl/worker.asmx")
Return New WebWorker.workerSoapClient(binding, endpoint)
End Function
Change
from
<security mode="None">
to
<security mode="Transport">
in your web.config file. This change will allow you to use https instead of http
Are you running this on the Cassini (vs dev server) or on IIS with a cert installed? I have had issues in the past trying to hook up secure endpoints on the dev web server.
Here is the binding configuration that has worked for me in the past. Instead of basicHttpBinding, it uses wsHttpBinding. I don't know if that is a problem for you.
<!-- Binding settings for HTTPS endpoint -->
<binding name="WsSecured">
<security mode="Transport">
<transport clientCredentialType="None" />
<message clientCredentialType="None"
negotiateServiceCredential="false"
establishSecurityContext="false" />
</security>
</binding>
and the endpoint
<endpoint address="..." binding="wsHttpBinding"
bindingConfiguration="WsSecured" contract="IYourContract" />
Also, make sure you change the client configuration to enable Transport security.
I had same exception in a custom binding scenario. Anybody using this approach, can check this too.
I was actually adding the service reference from a local WSDL file. It got added successfully and required custom binding was added to config file. However, the actual service was https; not http. So I changed the httpTransport elemet as httpsTransport. This fixed the problem
<system.serviceModel>
<bindings>
<customBinding>
<binding name="MyBindingConfig">
<textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
messageVersion="Soap11" writeEncoding="utf-8">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</textMessageEncoding>
<!--Manually changed httpTransport to httpsTransport-->
<httpsTransport manualAddressing="false" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous"
bypassProxyOnLocal="false"
decompressionEnabled="true" hostNameComparisonMode="StrongWildcard"
keepAliveEnabled="true" maxBufferSize="65536"
proxyAuthenticationScheme="Anonymous"
realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
useDefaultWebProxy="true" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="https://mainservices-certint.mycompany.com/Services/HRTest"
binding="customBinding" bindingConfiguration="MyBindingConfig"
contract="HRTest.TestWebserviceManagerImpl" name="TestWebserviceManagerImpl" />
</client>
</system.serviceModel>
References
WCF with custombinding on both http and https
I had the EXACT same issue as the OP. My configuration and situation were identical. I finally narrowed it down to being an issue in WCFStorm after creating a service reference in a test project in Visual Studio and confirming that the service was working. In Storm you need to click on the "Config" settings option (NOT THE "Client Config"). After clicking on that, click on the "Security" tab on the dialog that pops up. Make sure "Authentication Type" is set to "None" (The default is "Windows Authentication"). Presto, it works! I always test out my methods in WCFStorm as I'm building them out, but have never tried using it to connect to one that has already been set up on SSL. Hope this helps someone!
Ran into the same issue, this is how my solution turned out at the end:
<basicHttpsBinding>
<binding name="VerificationServicesPasswordBinding">
<security mode="Transport">
</security>
</binding>
<binding name="VerificationServicesPasswordBinding1" />
</basicHttpsBinding>
I basically replaced every occurrence of Http with Https. You can try adding both of them if you prefer.
If you do this programatically and not in web.config its:
new WebHttpBinding(WebHttpSecurityMode.Transport)
Its a good to remember that config files can be split across secondary files to make config changes easier on different servers (dev/demo/production etc), without having to recompile code/app etc.
For example we use them to allow onsite engineers to make endpoint changes without actually touching the 'real' files.
First step is to move the bindings section out of the WPF App.Config into it's own separate file.
The behaviours section is set to allow both http and https (doesn't seem to have an affect on the app if both are allowed)
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="true" />
And we move the bindings section out to its own file;
<bindings configSource="Bindings.config" />
In the bindings.config file we switch the security based on protocol
<!-- None = http:// -->
<!-- Transport = https:// -->
<security mode="None" >
Now the on site engineers only need to change the Bindings.Config file and the Client.Config where we store the actual URL for each endpoint.
This way we can change the endpoint from http to https and back again to test the app without having to change any code.
Hope this helps.
To re-cap the question in the OP:
I am connecting [to a WCF service] using WCFStorm which is able to retrieve all the meta data properly, but when I call the actual method I get:
The provided URI scheme 'https' is invalid; expected 'http'. Parameter name: via
The WCFStorm tutorials addresses this issue in Working with IIS and SSL.
Their solution worked for me:
To fix the error, generate a client config that matches the wcf service configuration. The easiest way to do this is with Visual Studio.
Open Visual Studio and add a service reference to the service. VS will generate an app.config file that matches the service
Edit the app.config file so that it can be read by WCFStorm. Please see Loading Client App.config files. Ensure that the endpoint/#name and endpoint/#contract attributes match the values in wcfstorm.
Load the modified app.config to WCFStorm [using the Client Config toobar button].
Invoke the method. This time the method invocation will no longer fail
Item (1) last bullet in effect means to remove the namespace prefix that VS prepends to the endpoint contract attribute, by default "ServiceReference1"
<endpoint ... contract="ServiceReference1.ListsService" ... />
so in the app.config that you load into WCFStorm you want for ListsService:
<endpoint ... contract="ListsService" ... />
I needed the following bindings to get mine to work:
<binding name="SI_PurchaseRequisition_ISBindingSSL">
<security mode="Transport">
<transport clientCredentialType="Basic" proxyCredentialType="None" realm="" />
</security>
</binding>
wsHttpBinding is a problem because silverlight doesn't support it!
I've added a "Connected Service" to our project by Visual Studio which generated a default method to create Client.
var client = new MyWebService.Client(MyWebService.Client.EndpointConfiguration.MyPort, _endpointUrl);
This constructor inherits ClientBase and behind the scene is creating Binding by using its own method Client.GetBindingForEndpoint(endpointConfiguration):
public Client(EndpointConfiguration endpointConfiguration, string remoteAddress) :
base(Client.GetBindingForEndpoint(endpointConfiguration),
new System.ServiceModel.EndpointAddress(remoteAddress))
This method has different settings for https service and http service.
When you want get data from http, you should use TransportCredentialOnly:
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.TransportCredentialOnly;
For https you should use Transport:
result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport;
In my case in web.config I had to change binding="basicHttpsBinding" to binding="basicHttpBinding" in the endpoint definition and copy the relative bindingConfiguration to basicHttpBinding section
<!-- Binding settings for HTTPS endpoint -->
<binding name="yourServiceName">
<security mode="Transport">
<transport clientCredentialType="None" />
<!-- Don't use message -->
</security>
</binding>
My solution, having encountered the same error message, was even simpler than the ones above, I just updated the to basicHttpsBinding>
<bindings>
<basicHttpsBinding>
<binding name="ShipServiceSoap" maxBufferPoolSize="512000" maxReceivedMessageSize="512000" />
</basicHttpsBinding>
</bindings>
And the same in the section below:
<client>
<endpoint address="https://s.asmx" binding="basicHttpsBinding" bindingConfiguration="ShipServiceSoap" contract="..ServiceSoap" name="ShipServiceSoap" />
</client>