Im trying to pass windows credentials into WCF service that requires windows authentication but it seems like my credentials are not making it into the service. My service does not throw any errors but when I check either of the 2 below they are empty.
var user = WindowsIdentity.GetCurrent().User;
var callerUserName = ServiceSecurityContext.Current.WindowsIdentity.User;
Here is my client side code
ServiceReference1.DispatchServiceClient service = new DispatchServiceClient();
service.ClientCredentials.Windows.ClientCredential = ServiceCredentialsManager.GetNetworkCredentials();
service.ClientCredentials.UserName.UserName= ServiceCredentialsManager.GetNetworkCredentials().UserName;
service.ClientCredentials.UserName.Password = ServiceCredentialsManager.GetNetworkCredentials().Password;
Client config -
<basicHttpBinding>
<binding name="BasicHttpsBinding_IDispatchService">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
<basicHttpsBinding>
<binding name="basicHttpsBindingMax" maxBufferSize="999999999"
maxReceivedMessageSize="999999999">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpsBinding>
</bindings>
Service config -
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpsBinding">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<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="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
Please note that in order to use Windows Authentication both service and the client application has to be run in the same Windows domain.
Please also make sure that that in the client the values You assign are not empty. Usually, the password isn't accessible from code when Windows authentication is used.
If the service client is authenticated using Windows Authentication, You probably shouldn't manually pass the credentials to the service. The authentication process should be handled automatically by the WCF and doesn't rely simply on sending the credentials, but for example it can use Kerberos ticket instead.
Please take a look here for some description and code samples for client and service:
https://msdn.microsoft.com/en-us/library/ms734673%28v=vs.110%29.aspx
https://msdn.microsoft.com/en-us/library/ms733089%28v=vs.110%29.aspx
Update
After some research I've found several sources suggesting that setting credentials appropriately in the client code may enable WCF to authenticate from outside the domain:
https://devdump.wordpress.com/2009/04/29/wcf-windows-authentication-and-external-users/
http://subbusspace.blogspot.com/2009/10/accessing-wshttp-wcf-service-from.html
The code samples suggested in those articles are similar, but slightly different to the one You've posted in the question. I haven't tested those methods and they may not work in all scenarios.
Related
I am stuck in very odd situation and do not know how to solve this issue.
I have very simple WCF service working very fine with http BUT now I want to move it to https.
The issue is Server where it needs to be hosted. Server IIS have an alias name "server-test.local" (not "localhost") with http. Its is accessible locally with this alias name. And its mapped to a Domain name with https (example, https://rmt.XXXXXXX.com).
When I deploy my WCF to that server and check WSDL file, it has mapping of the local alias name instead of public domain name.
it is showing http://server-test.local/WCFService/Service.svc (WRONG)
I want mapping like https://rmt.XXXXXXXX.com/WCFService/Service.svc (CORRECT)
Service web.config
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<pages controlRenderingCompatibilityVersion="4.0"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text">
<readerQuotas maxDepth="2000000" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<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>
When I add service reference to app. It adds following endpoint which is not conrrect.
Client App.config (endpoint)
<endpoint address="http://server-test.local/WCFService/Service.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IProcessing"
contract="WCFService.IService" name="BasicHttpBinding_IProcessing" />
I am able to access the url and WSDL file through browser but not able to consume any Service methods. I am getting error "There is no endpoint which can accept the message."
I think I am missing something obvious here. Please suggest me changes.
You can try to change some simple steps in the web.config file, you can refer to this post for details.
1.Enable transport level security in the web.config file of the service:
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
2.Use the bindingConfiguration tag to specify the binding name and the behaviorConfiguration tag to configure the behavior, and then specify the address of the managed service. The code is as follows:
<service name="***" behaviorConfiguration="***">
<endpoint address= https://rmt.XXXXXXXX.com/WCFService/Service.svc
binding="basicHttpBinding"
bindingConfiguration="???"
contract="WCFService.IService"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
recently I've met problem with EndpointNotFoundException when calling from another Web Application (WCF or REST API) in WCF.
I'm trying to connect to external WCF service which needs login and password identification (right now I'm working on test enviroment prepared by provider).
Then exception occours:
There was no endpoint listening at https://xxx/yyy.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details
This problem not occurs in Console Application - works smooth but only when I'm creating simple projects such as WCF or REST API.
<bindings>
<customBinding>
<binding name="custom">
<security defaultAlgorithmSuite="Default" authenticationMode="UserNameOverTransport"
requireDerivedKeys="true" includeTimestamp="true" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
<localClientSettings detectReplays="false" />
<localServiceSettings detectReplays="false" />
</security>
<textMessageEncoding messageVersion="Soap11WSAddressing10" />
<httpsTransport maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"/>
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="https://uslugaterytws1test.stat.gov.pl/TerytWs1.svc"
binding="customBinding" bindingConfiguration="custom" contract="TerytWsTest.ITerytWs1"
name="custom" />
</client>
<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="basicHttpsBinding" scheme="https" />
</protocolMapping>
TerytWs1Client tc = new TerytWs1Client();
tc.ClientCredentials.UserName.UserName = "TestPubliczny";
tc.ClientCredentials.UserName.Password = "1234abcd";
var zalogowany = tc.CzyZalogowany();
As well I have tried:
try {
var proxy = new ChannelFactory<TerytWsTest.ITerytWs1>("custom");
proxy.Credentials.UserName.UserName = "TestPubliczny";
proxy.Credentials.UserName.Password = "1234abcd";
var result = proxy.CreateChannel();
var test = result.CzyZalogowany();
}
catch (Exception ex) { }
First of all you have to make sure that your WCF service has been started, you can check whether the WCF service has been started through the browser:
Then you can call the WCF service by adding a service reference:
After clicking OK, it will automatically generate the proxy class, we can call the WCF service through the proxy class:
I have a web service(using wsHttpBinding and SSL) developed in Visual Studio 2017. Whenever i introduce the following line, the Web Service just fails and it goes into the "faulted" state.
<authentication certificateValidationMode="Custom" customCertificateValidatorType="SampleProject.SampleService.AuthenticationCertificateValidator, SampleProject.SampleService"/>
The error message when attempting to "Add Service Reference" on the client side i recieve the following error:
There was an error downloading 'https://localhost/SampleService/service'.
The request failed with HTTP status 404: Not Found.
Metadata contains a reference that cannot be resolved:
'https://localhost/SampleService/service'.
There was no endpoint listening at https://localhost/SampleService/service
that could accept the message. This is often caused by an incorrect address
or SOAP action. See InnerException, if present, for more details.
The remote server returned an error: (404) Not Found.
If the service is defined in the current solution, try building the
solution and adding the service reference again.
Here is the code relating to the validator.
public class AuthenticationCertificateValidator : X509CertificateValidator
{
string allowedIssuerName;
public AuthenticationCertificateValidator(string allowedIssuerName)
{
if (allowedIssuerName == null)
{
throw new ArgumentNullException("allowedIssuerName");
}
this.allowedIssuerName = allowedIssuerName;
}
public override void Validate(X509Certificate2 certificate)
{
// Check that there is a certificate.
if (certificate == null)
{
throw new ArgumentNullException("certificate");
}
// Check that the certificate issuer matches the configured issuer.
if (allowedIssuerName != certificate.IssuerName.Name)
{
throw new SecurityTokenValidationException
("Certificate was not issued by a trusted issuer");
}
}
}
However the service works fine when i only have the "ChainTrust" line enabled as shown below:
<!--certificateValidationMode="Custom"
customCertificateValidatorType
="SampleProject.SampleService.AuthenticationCertificateValidator,
SampleProject.SampleService"/>-->
<authentication certificateValidationMode="ChainTrust" />
Ideally i want my service and client to use ChainTrust and also use the custom validator class if that's possible?
Therefore what am i doing wrong regarding configuration? Am i missing something from the config file?
Here is the full Service config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="SampleProject.SampleService.SampleService"
behaviorConfiguration="SampleService_Behavior">
<endpoint
address="https://localhost/SampleService/service"
binding="wsHttpBinding"
bindingConfiguration="SampleService_Binding"
contract="SampleProject.SampleService.ISampleService" />
<endpoint
address="https://localhost/SampleService/service/mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="SampleService_Binding"
maxReceivedMessageSize="2147483647"
maxBufferPoolSize="2147483647" >
<readerQuotas
maxDepth="2147483647"
maxStringContentLength="2147483646"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647"/>
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="Certificate" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="SampleService_Behavior">
<!--Service metadata is needed for when you have an mex endpoint exposed-->
<serviceMetadata httpsGetEnabled="true" httpsGetUrl="https://localhost/SampleService/service/mex"/>
<serviceDebug includeExceptionDetailInFaults="True"/>
<!--The serviceCredentials behavior defines a service certificate
which is used by the service to authenticate itself to its
clients and to provide message protection. -->
<serviceCredentials>
<serviceCertificate
findValue="SampleServer"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
<clientCertificate>
<!--<authentication certificateValidationMode="ChainTrust" />-->
<authentication
certificateValidationMode="Custom"
customCertificateValidatorType
="SampleProject.SampleService.AuthenticationCertificateValidator,
SampleProject.SampleService"/>
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webBehaviour">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
if someone could assist me that would be much appreciated.
I created a HTTP wcf service that will be consumed by a windows client and utilized. I had no issue until I was using HTTP. Now my customer wants to change the site to HTTPS. So for development purpose I have used IIS express certificate and setup the service. Now my service is up and running in IIS with iisexpress self signed certificate. I am able to browse my new https service via browser as well as wcf test client tool.
But when I try invoke the method from my windows application to new https wcf service. My service instance is created but only during invoking a method I get following error:
System.ServiceModel.ActionNotSupportedException was unhandled by user code
HResult=-2146233087
Message=The message with Action 'http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence' 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).
In service my binding config (config 3 is being used at https mode and config 2 was used during http mode) are as follows:
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding_IPGPService">
<!--config test 1 - start -->
<!--<security mode="None">
<transport clientCredentialType="None" />
<message establishSecurityContext="false" />
</security>-->
<!--config test 1 - end -->
<!--config test 2 - start -->
<!--<security mode="None" />
<reliableSession enabled="true" />-->
<!--config test 2 - end -->
<!--config test 3 - start -->
<!--<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None"/>
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>-->
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
<!--config test 3 - end -->
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="PGPService.PGPService">
<endpoint address="" binding="wsHttpBinding" contract="PGPService.IPGPService" bindingConfiguration="wsHttpBinding_IPGPService" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<!--<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> -->
<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"/>-->
<!--test config - start-->
<serviceDebug includeExceptionDetailInFaults="True" />
<!--test config - end-->
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
In client we use custom binding to create service instance.
url = "https://localhost:550/TestService/TestService.svc";
customBinding = new CustomBinding();
customBinding.Elements.Add(new ReliableSessionBindingElement());
customBinding.Elements.Add(new HttpsTransportBindingElement());
EndpointAddress endpointAdress = new EndpointAddress(url);
pgpServiceClientInstance = new PGPServiceClient(customBinding, endpointAdress);
pgpServiceClientInstance.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.Root,
X509FindType.FindByThumbprint,
"03815c894b62dcf2d17336ade2d9ca61ddb7f92c");
After adding service reference the app.config generated on my Windows application is as follows:
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IPGPService">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost:550/TestService/TestService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IPGPService"
contract="PGPServiceReference.IPGPService" name="WSHttpBinding_IPGPService" />
</client>
So now I can see my service instance is getting successfully created. but on the time of invoking a method I get above error.
There is no code changed before and after moving to https on service end. It is the same service code. It was completely working fine on http but is broken on https.
I have completely removed the service reference and added it newly after making my wcf service https. IIS express self signed certificate is installed and available already on my system. Both service and client are running in same system as of now since it is development
I am suspecting I am having a configuration problem....but with less experience I could not figure out.
Actually it was an additional binding during service instantiation that was causing the problem. Got it sorted by commenting below line in instantiation part.
url = "https://localhost:550/TestService/TestService.svc";
customBinding = new CustomBinding();
//customBinding.Elements.Add(new ReliableSessionBindingElement());
customBinding.Elements.Add(new HttpsTransportBindingElement());
This helped me to proceed with developing the entire service and client.
So that concludes my fix for above issue.
Further down the lane since i am a newbie to wcf service i faced following problems which i faced and solved. Someone who is struggling like me can use below step if you are facing my errors
Next my service had problems accessing folder
Fix: add seperate application pool with an service or administrator account with enough privileges.
To add wcf session to existing code.
Fix: This is where i am facing problem because i was using wshttpbinding with transport security. Then after browsing several materials and codes understood i have to make my config to custombinding with reliablesession and httpstransport to proceed further with development. so my config roughly appears as
<customBinding abc of wcf>
<reliableSession/>
<httpsTransport/>
<\customBinding>
And also uncommented above line of service instantiation after understanding its real purpose.No need for any values in reliable session tag and httpsTransport for basic support of security.
This solved my second issue.
However i am facing wsdl import error in wcf client test tool now which i am struggling now to solve. svcutil proxy generation option or add service refrence with uncheked assembly option doesnt seem to be working. Also i noticed that even if add my service refrence freshly to client there is no configurations generated to my app.config file surprisingly.....and above mentioned options dont help.....looking for experts ideas....
Fix : ??? Expolring....
Souls who read this are welcome to give answer/suggestion.
When I log in into wcf localhost/Service1.svc I get Error:
The authentication schemes configured on the host ('Basic') do not
allow those configured on the binding 'BasicHttpBinding'
('Anonymous'). Please ensure that the SecurityMode is set to
Transport or TransportCredentialOnly. Additionally, this may be
resolved by changing the authentication schemes for this application
through the IIS management tool, through the
ServiceHost.Authentication.AuthenticationSchemes property, in the
application configuration file at the
element, by updating the ClientCredentialType property on the binding,
or by adjusting the AuthenticationScheme property on the
HttpTransportBindingElement.
Web.Config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="Windows" />
<customErrors mode="Off"/>
</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">
<add name="BasicAuthHttpModule"
type="WCF_Customer_RentalObject.BasicAuthHttpModule, WCF_Customer_RentalObject"/>
</modules>
</system.webServer>
</configuration>
Do you know what I have to do?
When I add this:
<bindings>
<basicHttpBinding>
<binding> <!--Notice, no name attribute set-->
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
I get another error:
The authentication schemes configured on the host ('Basic') do not allow those configured on the binding 'BasicHttpBinding'
('Negotiate'). Please ensure that the SecurityMode is set to
Transport or TransportCredentialOnly. Additionally, this may be
resolved by changing the authentication schemes for this application
through the IIS management tool, through the
ServiceHost.Authentication.AuthenticationSchemes property, in the
application configuration file at the
element, by updating the ClientCredentialType property on the binding,
or by adjusting the AuthenticationScheme property on the
HttpTransportBindingElement.
1. Suggested client config:
<bindings>
<basicHttpBinding>
<binding name="basicEndpoint">
<security mode="Transport" >
<transport clientCredentialType="Basic"
proxyCredentialType="None"
realm="" />
</security>
</binding>
</basicHttpBinding>
May be mode="TransportCredentialOnly"> is OK
but <transport clientCredentialType="Windows" />
is probably not the best
2. Pass the credentials :
HelloServiceClient client = new HelloServiceClient();
client.ClientCredentials.UserName.UserName = userName;
client.ClientCredentials.UserName.Password = password;
String msg = client.SayHello(userName);
Hope it helps