I need some help, I'm trying to pass windows credentials to a WCF service. In the IIS only Windows authentication is enabled for those service and runs over https.
The server side config is:
<system.serviceModel>
<protocolMapping>
<add scheme="https" binding="basicHttpBinding" bindingConfiguration="httpsBinding"/>
</protocolMapping>
<bindings>
<basicHttpBinding>
<binding name="httpsBinding">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
and in the client side:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://myserver.net:4343/MyService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService"
contract="MyServiceReference.IMyService" name="BasicHttpBinding_IMyService" />
</client>
I'm trying to consume the service on this way:
Client = new MyServiceClient();
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
binding.MaxReceivedMessageSize = int.MaxValue;
binding.MaxBufferPoolSize = long.MaxValue;
binding.MaxBufferSize = int.MaxValue;
EndpointAddress ep = new EndpointAddress("https://myserver.net:4343/MyService.svc");
Client = new COMINTSServiceClient(binding, ep);
Client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;
Client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
Client.Open();
Array[] obj = Client.RandomMethod();
This code doesn't work for me:
Client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;
Client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
In the service when ask for the user who is calling to the service using ServiceSecurityContext.Current.WindowsIdentity.Name allways get: ISS APPPOOL\ASP.NET v4.0 instead of the domain\user who is calling
The only way to make it work is write the username and password instead DefaultNetworkCredentials.
Client.ClientCredentials.Windows.ClientCredential.UserName = "DOMAIN\\user";
Client.ClientCredentials.Windows.ClientCredential.Password = "passw";
But I don't want a user/passw hardcoded.
Any help please?
Try:
Client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
Keep the assignment from CredentialCache.
I faced with similar issue - "ServiceSecurityContext.Current.WindowsIdentity.Name" on the server side returned wrong username, not Current Windows User on the client side. Turns out "Client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials" may get credentials from Windows Credential Manager:
I failed to find a solution to instruct WCF to avoid grabbing credentials from that storage. The workaround was to check if some credentials are stored for that IP address and remove them. I used "https://www.nuget.org/packages/CredentialManagement" for checking and removing. Here is the code:
var creds = new Credential();
creds.Type = CredentialType.DomainPassword;
creds.Target = address.Uri.Host;//address is WCF EndpointAddress
if (creds.Load() && creds.Username != System.Security.Principal.WindowsIdentity.GetCurrent().Name)
{
creds.Delete();
}
Related
After I moved WCF service and ASP.NET Core website to server I get following error:
The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'Negotiate, NTLM'.
I have enabled only Windows Authentication on WCF service with following web.config:
<system.serviceModel>
<client />
<behaviors>
<serviceBehaviors>
<behavior name="authBehavior">
<serviceAuthorization principalPermissionMode="UseWindowsGroups">
<authorizationPolicies>
<add policyType="WCF.AuthorizationPolicy, WCF" />
</authorizationPolicies>
</serviceAuthorization>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCF.IdentityValidator, WCF" />
<serviceCertificate findValue="16E86CCAFFE6211DAE6E841B984F71FB7609D349" storeLocation="LocalMachine" x509FindType="FindBySerialNumber" storeName="My" />
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpsBinding>
<binding name="basicHttpsEndpointBinding" maxReceivedMessageSize="1073741824" maxBufferSize="1073741824" maxBufferPoolSize="1073741824">
<readerQuotas maxDepth="32" maxArrayLength="1073741824" maxStringContentLength="1073741824" />
<security mode="Transport">
<transport clientCredentialType="Ntlm" />
</security>
</binding>
</basicHttpsBinding>
</bindings>
<services>
<service name="WCF.MyService" behaviorConfiguration="authBehavior">
<endpoint address="" binding="basicHttpsBinding" bindingConfiguration="basicHttpsEndpointBinding" contract="WCF.IMyService">
<identity>
<dns value="example.com" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
ASP.NET Core client:
BasicHttpsBinding binding = new BasicHttpsBinding
{
MaxBufferPoolSize = 1073741824,
MaxBufferSize = 1073741824,
MaxReceivedMessageSize = 1073741824
};
binding.ReaderQuotas.MaxDepth = 32;
binding.ReaderQuotas.MaxArrayLength = 1073741824;
binding.ReaderQuotas.MaxStringContentLength = 1073741824;
binding.Security.Mode = BasicHttpsSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
MyServiceClient client = new MyServiceClient(binding, new EndpointAddress(new Uri("https://example.com/MyService.svc"), new DnsEndpointIdentity("mydomain.com")));
client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
client.ClientCredentials.Windows.ClientCredential.Domain = Configuration.GetSection("WCF")["MyServiceDomain"];
client.ClientCredentials.Windows.ClientCredential.UserName = Configuration.GetSection("WCF")["MyServiceUserName"];
client.ClientCredentials.Windows.ClientCredential.Password = Configuration.GetSection("WCF")["MyServicePassword"];
// client call
I run out of ideas what could be wrong. If I change Ntlm to Windows in config/code then I get error with client authentication scheme 'Negotiate'. Can I somehow use both or I have to remove somehow Negotiate/Ntlm from IIS?
Thanks for any idea!
SOLUTION!
Method 1 from article https://blogs.msdn.microsoft.com/distributedservices/2009/11/10/wcf-calling-wcf-service-hosted-in-iis-on-the-same-machine-as-client-throws-authentication-error/
Requires server reboot!
I found this article which offers solution for my issue
Article: https://blogs.msdn.microsoft.com/distributedservices/2009/11/10/wcf-calling-wcf-service-hosted-in-iis-on-the-same-machine-as-client-throws-authentication-error/
Use method 1. Requires server reboot!
In registry I used CNAME like
mySubdomain
mySubdomain.myDomain.com
localhost
192.168.0.xxx
192.168.0.1 (default gateway)
xx.xx.xx.xx (my ip address)
I need to access web service which required HTTP basic authentication and I consumed successfully using SoapUI.
SoapUI
Now I need to implement in .net.
I created a new C# Console project in Visual Studio and added a web reference for https://itestapi.tracelink.com/soap/snx/snrequest?wsdl
Below is my code and I am getting Access Denied
C# code
ServiceReference1.snrequestClient snx = new ServiceReference1.snrequestClient();
snx.ClientCredentials.UserName.UserName = "abc#gmail.com";
snx.ClientCredentials.UserName.Password = "xyz#2018";
ServiceReference1.objectKey objectKey = new ServiceReference1.objectKey
{
Name = ServiceReference1.objectIdentifierType.GTIN,
Value = "1111111"
};
ServiceReference1.ReferenceDocuments ReferenceDocuments = new ServiceReference1.ReferenceDocuments();
snx.serialNumbersRequest("11111", "11111", ServiceReference1.idType.GS1_SER, ServiceReference1.encodingType.SGTIN, 2, objectKey, "", ReferenceDocuments);
App.config
<bindings>
<basicHttpBinding>
<binding name="snrequestPortBinding">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
<binding name="snrequestPortBinding1" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://itestapi.tracelink.com:443/soap/snx/snrequest"
binding="basicHttpBinding" bindingConfiguration="snrequestPortBinding"
contract="ServiceReference1.snrequest" name="snrequestPort" />
</client>
I am using a ChannelFactory to call into a WCF service (as the target service location will change depending on environment and I need the URL to be configurable). However I get the error:
The HTTP request is unauthorized with client authentication scheme
'Anonymous'. The authentication header received from the server was
'Negotiate,NTLM'.
My calling code
var myBinding = new BasicHttpBinding();
var myEndpoint = new EndpointAddress(webserviceAddress);
var myChannelFactory = new ChannelFactory<IObjectService>(myBinding, myEndpoint);
var serviceClient = myChannelFactory.CreateChannel();
My WCF service web.config system.servicemodel section
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" minFreeMemoryPercentageToActivateService="0" />
</system.serviceModel>
The service should be authenticated based on Windows Authentication. I would have thought by default the calling code above would use Windows Authentication to pass the account that the code is running as (a service account) but it seems to be sending anonymous
You must set the mode to transport with message credentials, as shown in the following code:
var myBinding = new BasicHttpBinding();
myBinding.Security.Mode = SecurityMode.TransportCredentialOnly;
As an alternative, you can set the mode in the constructor of the binding:
var myBinding = new BasicHttpBinding(SecurityMode.TransportCredentialOnly);
Also set the ClientCredential:
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
My issue is that i have this Webservice EService that works really great in my debug projekt, but when i implement it into a WinForm projekt, and put the service on a server. I get this error when crateing the client?
An unhandled exception of type 'System.InvalidOperationException'
occurred in System.ServiceModel.dll
Could not find default endpoint element that references contract '{0}' 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.
App.config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IEService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://Domane.dk/EService.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IEService" contract="IEService"
name="BasicHttpBinding_IEService" />
</client>
Web.config
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="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>
<protocolMapping>
<add binding="basicHttpBinding" scheme="http" />
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<bindings>
<basicHttpBinding>
<binding name="" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" transferMode="Streamed">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
The way im calling it
using (var test = new EServiceAPI.EServiceClient())
{
test.OpdaterLeastDatoWinPLC(connstr);
}
I cant se the reason why it fails. Sorry for being such a newbi. And yes i've harvestet the internet for 2 days trying to find a solusion now.
I have had the same problem when using a web service in a dll.
Try this:
using (var test = CreateWebServiceInstance("http://url.to.mywebservice.com"))
{
test.OpdaterLeastDatoWinPLC(connstr);
}
Enter the correct url to the web service above and create the client using the code below. You still need to add the web service to the project so that the class EServiceClient is created for you.
internal static EServiceAPI.EServiceClient CreateWebServiceInstance(string url) {
BasicHttpBinding binding = new BasicHttpBinding();
binding.SendTimeout = TimeSpan.FromMinutes(10);
binding.OpenTimeout = TimeSpan.FromMinutes(1);
binding.CloseTimeout = TimeSpan.FromMinutes(1);
binding.ReceiveTimeout = TimeSpan.FromMinutes(20);
binding.AllowCookies = false;
binding.BypassProxyOnLocal = false;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.MessageEncoding = WSMessageEncoding.Text;
binding.TextEncoding = Encoding.UTF8;
binding.TransferMode = TransferMode.Buffered;
binding.UseDefaultWebProxy = true;
binding.MaxReceivedMessageSize = 5242880;
return new EServiceAPI.EServiceClient(binding, new EndpointAddress(url));
}
If it works you can modify the settings above to suit your needs better.
I think this has to do with the <endpoint address="http://Domane.dk/EService.svc" i believe it should be a relative path when using on a server.
Like:
<endpoint address="./EService.svc"
Is it possible to call a WCF service from a universal application?
I added a service reference and the proxy was generated just fine.
But when creating a NetTcpBinding programmatically and passing that to the proxy's constructor the service model throws the exception PlatformNotSupported.
Both running the app in the simulator and on the local machine generates the same exception.
An exception of type 'System.PlatformNotSupportedException' occurred
in System.Private.ServiceModel.dll but was not handled in user code
"this operation is not supported"
EndpointAddress address = new EndpointAddress("net.tcp://test:9000/ServicesHost/PublishService");
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
PublishingService.PublishClient proxy = new PublishingService.PublishClient(binding, address);
Does anybody have an example of a working WCF client in a UAP?
EDIT
It has something to do with the service being a duplex service!
The original contract:
[ServiceContract(CallbackContract = typeof(IPublishCallback))]
public interface IPublish { }
After removing the CallbackContract attribute the UAP client can create a connection, so basic WCF works.
So I guess it's better to rephrase the question.
Is it possible to create a duplex WCF client in a universal application?
edit servicemodel for the host
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTcpPublishService" openTimeout="00:00:10" receiveTimeout="infinite">
<reliableSession inactivityTimeout="24.20:31:23.6470000" enabled="true" />
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehaviour">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="serviceBehaviour" name="PublishService.Publish">
<endpoint binding="mexHttpBinding" name="mexPublishService"
contract="IMetadataExchange" />
<endpoint address="PublishService" binding="netTcpBinding" bindingConfiguration="netTcpPublishService"
name="netTcpPublishService" contract="PublishService.IPublish" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8004/ServicesHost/PublishService" />
<add baseAddress="net.tcp://localhost:9004/ServicesHost/PublishService" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
Yes, it is possible. This is how i connect in a sample app i did a while ago:
using Tradeng.Srvc.Client.WinAppSimple.SrvcRefTradeng;
private InstanceContext instanceContext;
private TradengSrvcClientBase serviceProxy;
instanceContext = new InstanceContext(this);
serviceProxy = new TradengSrvcClientBase(instanceContext);
bool result = await serviceProxy.ConnectAsync();
if (result)
{
// connected...
}
I used the binding from the config file that is generated when you add a reference to your service.
This is what the app looks like. Cutting edge stuff.... :O)
https://www.youtube.com/watch?v=YSg6hZn1DpE
The service itself is running as a WebRole on Azure, by the way.