WCF service worked with windows authentication, switched to use SSL now it wants anonymous - wcf

I have created a WCF service with Windows authentication that worked correctly.
Now I am trying to add SSL. After following the steps, it now seems to be using anonymous authentication, giving this error:
The HTTP request was forbidden with client authentication scheme 'Anonymous'.
Any clues would be appreciated.
We are using IIS 7.5 on Windows Server 2008 R2 and .Net version 4
The config file that worked correctly had this service model (server side):
<system.serviceModel>
<bindings />
<client />
<services>
<service name="WCFServiceTest.Service1" behaviorConfiguration="WCFServiceBehavior">
<endpoint address="" binding="wsHttpBinding" contract="WCFServiceTest.WCFService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFServiceBehavior">
<serviceMetadata httpGetEnabled="True" policyVersion="Policy15" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
This is the changed configuration
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="TransportWsSecurity">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client />
<services>
<service name="WCFServiceTest.Service1" behaviorConfiguration="WCFServiceBehavior">
<endpoint address="" binding="wsHttpsBinding"
bindingConfiguration="TransportWsSecurity"
contract="WCFServiceTest.WCFService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
<host>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFServiceBehavior">
<serviceMetadata httpsGetEnabled="True" policyVersion="Policy15" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
This is the code that calls the service. It never gets to the IgnoreCertificateErrorHandler which just returns true:
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(IgnoreCertificateErrorHandler);
WCFService1Client client = new WCFService1Client();
client.ClientCredentials.Windows.ClientCredential.UserName = Utility1.GetConfig("RemoteLogin");
client.ClientCredentials.Windows.ClientCredential.Password = Utility1.GetConfig("RemotePassword");
try
{
result = client.SendUpdatesFromLocation(temp);
}
catch (FaultException<WCFProcessFault> ex)
{
string op = ex.Detail.Operation;
string err = ex.Detail.Notes;
}
finally
{
client.Close();
}
WCFService1Client client = new WCFService1Client();
client.ClientCredentials.Windows.ClientCredential.UserName = Utility1.GetConfig("RemoteLogin");
client.ClientCredentials.Windows.ClientCredential.Password = Utility1.GetConfig("RemotePassword");
try
{
result = client.SendUpdatesFromLocation(temp);
}
catch (FaultException<WCFProcessFault> ex)
{
string op = ex.Detail.Operation;
string err = ex.Detail.Notes;
}
finally
{
client.Close();
}

<bindings>
<wsHttpBinding>
<binding name="TransportWsSecurity">
<security mode="Transport">
<transport clientCredentialType="Ntlm"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
Try the above changes. This will use Ntlm rather than Negotiate (Kerberos) for auth. It is very very likely you haven't setup your server for Kerberos auth.

Related

http wcf error "Could not find a base address that matches scheme https for the endpoint with binding MetadataExchangeHttpsBinding..."

am getting this error when i try to call my custom svc file from sharpoint. i have posted my web.config file here, could you guys tell wats wrong with this.
am trying to have my custom webservice in the sharepoint, so i created a project but due to this error i could not browse my web methods.
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="AlertWcfService.CustomServiceBehaviour"
name="AlertWcfService.AlertService">
<endpoint address="http://localhost:2000/" binding="basicHttpBinding" bindingConfiguration="basicHttpBindingConfiguration"
contract="AlertWcfService.IAlertService" >
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:2000/"></add>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBindingConfiguration">
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="AlertWcfService.CustomServiceBehaviour">
<!--<serviceMetadata httpsGetEnabled="false"/>-->
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
The error is that you're not using HTTPS, but you're using an MEX binding for HTTPS rather than HTTP. TO fix this, change this line:
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
To
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
In your interface declaration IAlertService, add the name attribute beside the namespace if you do not have it yet...
[ServiceContract(Name = "NameNeeded", Namespace = "http://blahbalh")]
public interface IAlertService
{
.....
}

WCF custom username and password validation is not executed

I have a WCF service hosted on IIS 7.5 with the settings of basicHttpBinding binding and TransportWithMessageCredential security. I would like to send a FaultException to the client in case of failed authentication but unfortunately the Validate method of custom validator class is not executed.
I have read here, that custom validator works only for self-hosting scenario:
Is it true, or I made a mistake somewhere?
public class ServiceUserNamePasswordValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
if (!(userName == MobilApp.Helper.SiteGlobal.UserName && password == MobilApp.Helper.SiteGlobal.Password))
{
throw new FaultException("Unknown Username or Incorrect Password");
}
}
}
web.config:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="True" />
<bindings>
<basicHttpBinding>
<binding name="ServiceBinding" useDefaultWebProxy="false">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Certificate" />
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="Service.TestService" behaviorConfiguration="CustomValidator">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="ServiceBinding"
bindingNamespace="https://service/TestService/"
contract="Service.ITestService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://service/TestService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CustomValidator">
<useRequestHeadersForMetadataAddress/>
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="True" httpsGetUrl="wsdl" />
<serviceDebug includeExceptionDetailInFaults="false" httpHelpPageEnabled="false" httpsHelpPageEnabled="true" />
<serviceCredentials>
<clientCertificate>
<authentication
certificateValidationMode="ChainTrust"
revocationMode="NoCheck" />
</clientCertificate>
<serviceCertificate
findValue="test.com"
x509FindType="FindBySubjectName"
storeLocation="LocalMachine"
storeName="My" />
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="ServiceUserNamePasswordValidator, Service" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
Thank you.

How to avoid the service certificate?

"The service certificate is not provided. Specify a service certificate in ServiceCredentials." is what I see when I point my browser to the svc file address
as you can see below, my serviceCredentials section is commented (it's just an example from some book), since I don't want any certificate. But apparently I can't avoid it... what can I do ?
I can't use basicHttpBinding because I want sessions support
my binding:
<wsHttpBinding>
<binding name="BindingToViewer" sendTimeout="00:25:00">
<security mode="Message">
<message clientCredentialType = "None"/>
</security>
</binding>
</wsHttpBinding>
my service:
<service name="SomeNs.Whatever.ServName" behaviorConfiguration="NoPrinPermMode">
<endpoint address="" binding="wsHttpBinding"
bindingConfiguration="BindingToViewer"
contract="SomeNs.Whatever.IMyInterface">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="https://localhost/"/>
</baseAddresses>
</host>
</service>
my service behaviors:
<serviceBehaviors>
<behavior name="NoPrinPermMode">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483646"/>
<serviceAuthorization principalPermissionMode="None" />
<!--<serviceCredentials>
<serviceCertificate
findValue = "MyServiceCert"
storeLocation = "LocalMachine"
storeName = "My"
x509FindType = "FindBySubjectName"/>
</serviceCredentials>-->
</behavior>
</serviceBehaviors>
You have configured message security in WSHttpBinding which implies your service must supply a certificate (unless you use windows auth). The question is what kind of security you need if at all?
Do not use https in base address:
<add baseAddress="https://localhost/"/>
use instead:
<add baseAddress="http://localhost/"/>
and remove httpsGetEnabled:
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
to:
<serviceMetadata httpGetEnabled="True" />
and remove identity as you do not need to authentificate service
<identity>
<dns value="localhost" />
</identity>
edit
remove also
<security mode="Message">
<message clientCredentialType = "None"/>
</security>

Contract requires Session, but Binding ‘WSHttpBinding’ doesn’t support it or isn’t configured properly to support it

I have specified the service contract to require the session.
[ServiceContract(SessionMode = SessionMode.Required)]
public interface ITicketSales
{
}
The service decorated like this:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
public class TicketSalesService : ITicketSales
{
}
Here is my App.config file:
<system.serviceModel>
<services>
<service name="InternetRailwayTicketSales.TicketSalesImplementations.TicketSalesService" behaviorConfiguration="defaultBehavior">
<host>
<baseAddresses>
<add baseAddress = "https://localhost/TicketSales/"></add>
</baseAddresses>
</host>
<endpoint address="MainService" binding="wsHttpBinding" bindingConfiguration="wsSecureConfiguration"
contract="InternetRailwayTicketSales.TicketSalesInterface.ITicketSales" />
<endpoint address="mex" binding="mexHttpsBinding"
contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="wsSecureConfiguration">
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="defaultBehavior">
<serviceThrottling maxConcurrentInstances="5000" maxConcurrentSessions="5000"/>
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
When I press F5 I receive the error message "Contract requires Session, but Binding ‘WSHttpBinding’ doesn’t support it or isn’t configured properly to support it."
I really need the channel which supports SSL and requires session.
You can support sessions by enabling message security:
<binding name="wsHttpSecureSession">
<security>
<message establishSecurityContext="true"/>
</security>
</binding>
If you need to go with transport security you may need to specify a client credential type

WCF 3.5 UserNameAuthentication is not working?

What I'm trying to do is to secure my service. To do this I'm using UserNameAuthentication. I did the binding and everything but some reason when I start the service I don't get the Validation prompt! Validate method is not triggered!
Here is my webConfig
I don't know what I'm missing here!
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<services>
<service behaviorConfiguration="IPhone.Service1Behavior" name="MobileService.IPhone">
<endpoint address="" binding="wsHttpBinding" contract="MobileService.IIPhone" bindingConfiguration="SafeServiceConf">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="IPhone.Service1Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MobileService.CustomValidator, MobileService" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="SafeServiceConf" maxReceivedMessageSize="65536">
<readerQuotas maxStringContentLength="65536" maxArrayLength="65536"
maxBytesPerRead="65536" />
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
Here is my code in IPhone.svc for validation
I put the CustomValidator class inside the service!
public class CustomValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName == "test" && password == "test")
return;
throw new SecurityTokenException(
"Unknown Username or Password");
}
}
Any help?
The validation prompt would not come from WCF. The UI is responsible for that (i.e. ASPX web form).
To pass a user name and password from a client to a service, you would do something like this:
proxy.ClientCredentials.UserName.UserName = "myUserName";
proxy.ClientCredentials.UserName.Password = "password";