The caller was not authenticated by the service - wcf

I have build a simple WCF service using wsDualHttpBinding. It is working fine at local end but it throws a error when I publish the service on a different server and try to consume that service in a WPF project.
Error:
System.ServiceModel.SecurityNegotiationException "The caller was not authenticated by the service."
InnerException:
System.ServiceModel.FaultException "The caller was not authenticated by the service."
Server Config:
<system.serviceModel>
<services>
<service name="VetChat.Service.VetChatService" behaviorConfiguration="wsDualHttpBinding.SampleServiceBehavior">
<!-- Service Endpoints -->
<host>
<baseAddresses>
<add baseAddress="http://service.softprodigy.com:8090/VetChatService.svc"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsDualHttpBinding" contract="VetChat.Service.IVetChatService">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="VPS" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="wsDualHttpBinding.SampleServiceBehavior">
<!-- 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="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="VetChat.Service.UserNamePassValidator, VetChat.Service" />
<serviceCertificate findValue="MyName" storeLocation="CurrentUser" storeName="TrustedPeople" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Client Config:
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_IVetChatService" />
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="http://service.softprodigy.com:8090/VetChatService.svc"
binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IVetChatService"
contract="ServiceReference1.IVetChatService" name="WSDualHttpBinding_IVetChatService">
<identity>
<dns value="VPS" />
</identity>
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="MyName" x509FindType="FindBySubjectName"
storeLocation="CurrentUser" storeName="TrustedPeople" />
<serviceCertificate>
<defaultCertificate findValue="MyName" storeLocation="CurrentUser" storeName="TrustedPeople" x509FindType="FindBySubjectName" />
<authentication certificateValidationMode="PeerTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Interface:
[ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
public interface IVetChatService
{
[OperationContract(IsOneWay = true)]
void DoWork();
}
public interface ICallback
{
[OperationContract(IsOneWay = true)]
void Notify(string value);
}
Interface Implementation:
public class VetChatService : IVetChatService
{
public void DoWork()
{
//Thread.Sleep(5000);
OperationContext.Current.GetCallbackChannel<ICallback>().Notify("Hello");
}
}
Validte username password service class:
namespace VetChat.Service
{
class UserNamePassValidator :
System.IdentityModel.Selectors.UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName == null || password == null)
{
throw new ArgumentNullException();
}
if (!(userName == UserName && password == Password))
{
//throw new FaultException("Incorrect Username or Password");
}
}
}
public class Service
{
}
}
Call method:
InstanceContext instanceContext = new InstanceContext(new SampleServiceCallback());
ServiceReference1.VetChatServiceClient sampleServiceClient = new ServiceReference1.VetChatServiceClient(instanceContext);
sampleServiceClient.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.TrustedPeople,
X509FindType.FindBySubjectName,
"MyName");
sampleServiceClient.ClientCredentials.UserName.UserName = UserName;
sampleServiceClient.ClientCredentials.UserName.Password = Password;
//sampleServiceClient.Open();
sampleServiceClient.DoWork();
Response Callback:
public class SampleServiceCallback : ServiceReference1.IVetChatServiceCallback
{
#region ISampleServiceCallback Members
public void Notify(string value)
{
MessageBox.Show(value);
}
#endregion
}
Thanks

Related

Hosting WCF as Windows service " Service was started and Stopped"

I am hosting WCF as Windows Service using net.tcp. After installing the windows service when I start the service, I get that service was started and stopped.
The error says in order to In order to add an endpoint to the service 'MYService', a non-empty contract name must be specified.
at System.ServiceModel.Description.ConfigLoader.LookupContract(String contractName, String serviceName)
My OnStart function is as follows
protected override void OnStart(string[] args)
{
try
{
if (myServiceHost != null)
{
myServiceHost.Close();
}
myServiceHost = new ServiceHost(typeof(MYservice));
myServiceHost.Open();
}
catch (Exception ex)
{
log.Error("ONStart", ex);
throw;
}
}
The config file is as follows:
<serviceHostingEnvironment minFreeMemoryPercentageToActivateService="10" />
<services>
<service behaviorConfiguration="myServiceBehavior"
name="myNamespace.myTestService">
<endpoint binding="netTcpBinding" bindingConfiguration="netTCPBindingConfig" contract="myNamespace.ServiceInterface.ImyTestService" />
<endpoint binding="mexTcpBinding" bindingConfiguration="" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://10.1.3.69:8523/TestService" />
</baseAddresses>
<timeouts closeTimeout="10:00:10" openTimeout="10:01:00" />
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
In your config file, there is:
<endpoint binding="netTcpBinding" bindingConfiguration="netTCPBindingConfig" contract="myNamespace.ServiceInterface.ISomeService" /> `
Instead of ISomeService, you must specify whichever interface is implemented by MYService.
EDIT
Additionally, mex binding must have a contract specified, i.e. contract="IMetadataExchange"
EDIT AGAIN
For your convenience, this is how your mex binding should look like:
<endpoint binding="mexTcpBinding" address="mex" bindingConfiguration="" contract="IMetadataExchange" />
Please try this:
protected override void OnStart(string[] args)
{
try
{
myServiceHost = new ServiceHost(typeof(MYservice));
myServiceHost.Open();
Console.ReadKey();
}
catch (Exception ex)
{
log.Error("ONStart", ex); throw;
}
finally
{
myServiceHost.Close();
}
}

WCF service selfhosting

I am creating a WCF service with self hosting. I have found the following error i.e.:
The target assembly contains no service types. You may need to adjust the Code Access Security policy of this assembly.
The codes are as follows:
namespace MyJobs
{
public interface IJobsSvc
{
[OperationContract]
DataSet GetJobs();
[OperationContract]
Job GetJobInfo(int JobId);
[OperationContract]
List<Job> GetAllJobs();
}
}
namespace MyJobs
{
[DataContract]
public class Job
{
[DataMember]
public int JobId { get; set;}
[DataMember]
public string Description{get;set;}
[DataMember]
public int MinLevel { get; set; }
[DataMember]
public int MaxLevel { get; set; }
}
}
namespace MyJobs
{
public class JobsSvc:IJobsSvc
{
#region IJobsSvc Members
public System.Data.DataSet GetJobs()
{
string str = #"data source=PERSONAL-659BE4;database=practice;integrated security=true";
DataSet ds = new DataSet();
SqlConnection cn = new SqlConnection(str);
SqlDataAdapter da = new SqlDataAdapter("select * from Job1",cn);
da.Fill(ds);
return ds;
}
public Job GetJobInfo(int JobId)
{
string str = #"data source=PERSONAL-659BE4;database=practice;integrated security=true";
SqlConnection cn = new SqlConnection(str);
SqlCommand cmd = new SqlCommand("select * from Job1 where JobId="+JobId,cn);
cn.Open();
SqlDataReader dr = cmd.ExecuteReader();
Job obj = new Job();
if (dr.Read())
{
obj.JobId = JobId;
obj.Description = dr[1].ToString();
obj.MinLevel = Convert.ToInt32(dr[2]);
obj.MaxLevel = Convert.ToInt32(dr[3]);
}
else
{
obj.JobId = -1;
}
return obj;
}
public List<Job> GetAllJobs()
{
throw new NotImplementedException();
}
#endregion
}
}
The app.config file is:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="MyJobs.Job">
<endpoint address="" binding="wsHttpBinding" contract="MyJobs.IJobsSvc">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/Jobs/MyJobs/" />
</baseAddresses>
</host>
</service>
</services>
<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>
</system.serviceModel>
</configuration>
You need to add [ServiceContract] attribute to your IJobSvc interface
Update
Create the behavior to expose the metadata.
<serviceBehaviors>
<behavior name="SimpleServiceBehavior">
<!-- 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>
Then configure your service with this behavior:
<service name="MyJobs.Job" behaviorConfiguration="SimpleServiceBehavior">
<endpoint address="" binding="wsHttpBinding" contract="MyJobs.IJobsSvc">

WCF windows service, Service metadata may not be accessible

Hi a have WCF service libary with this configuration:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="Default" name="ComDocs.ControlServerServiceLibary.Concrete.TokenService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/TokenService" />
</baseAddresses>
</host>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="basic" binding="basicHttpBinding" contract="ComDocs.ControlServerServiceLibary.Abstract.ITokenService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
If I build it in debug, everything works fine on localhost. But if I make a Windows Service library with the same configuration:
public partial class TokenService : ServiceBase
{
ServiceHost _host = null;
public TokenService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Trace.WriteLine("Starting Token Service...");
_host = new ServiceHost(typeof(TokenService));
_host.Open();
}
protected override void OnStop()
{
Trace.WriteLine("Shutting down Token Service...");
if (_host != null)
{
_host.Close();
_host = null;
}
}
}
Install it with InstallUtil and start it:
but error:
I suspect this line is the culprit.
_host = new ServiceHost(typeof(TokenService));
TokenService is your Windows service class, not your WCF service class.

Unable to run first WCF service

This is my first WCF service and I am getting an error:
Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.
Code:
namespace WcfMathServiceLibrary
{
[ServiceContract]
public interface IMath
{
[OperationContract]
double Add(double i, double j);
[OperationContract]
double Sub(double i, double j);
[OperationContract]
Complex AddComplexNo(Complex i, Complex j);
[OperationContract]
Complex SubComplexNo(Complex i, Complex j);
}
[DataContract]
public class Complex
{
private int _real;
private int _imaginary;
[DataMember]
public int real { get; set; }
[DataMember]
public int imaginary { get; set; }
}
namespace WcfMathServiceLibrary
{
public class MathService : IMath
{
public double Add(double i, double j)
{
return (i + j);
}
public double Sub(double i, double j)
{
return (i - j);
}
public Complex AddComplexNo(Complex i, Complex j)
{
Complex result = new Complex();
result.real = i.real + j.real;
result.imaginary = i.imaginary + j.imaginary;
return result;
}
public Complex SubComplexNo(Complex i, Complex j)
{
Complex result = new Complex();
result.real = i.real - j.real;
result.imaginary = i.imaginary - j.imaginary;
return result;
}
}
Web.Config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="WcfMathServiceLibrary.MathService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/WcfMathServiceLibrary/MathService/"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="WcfMathServiceLibrary.MathService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" >
</endpoint>
</service>
</services>
<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>
I am not sure what is the issue. Could you please guide me?
I think your contract may need to point to the interface and not the concrete implementation
<endpoint address="" binding="wsHttpBinding" contract="WcfMathServiceLibrary.IMath">

CheckAccessCore not being called in custom ServiceAuthorizationManager

I am working on a WCF REST service that will be hosted within Azure and want to check the user id. To this end I have created a custom ServiceAuthorizationManager.
namespace SecureService
{
public class AccessControlServiceAuthorizationManager : ServiceAuthorizationManager
{
String serviceNamespace = String.Empty;
String acsHostname = String.Empty;
String trustedTokenPolicyKey = String.Empty;
String trustedAudience = String.Empty;
public AccessControlServiceAuthorizationManager()
{
try
{
serviceNamespace = RoleEnvironment.GetConfigurationSettingValue("serviceNamespace");
acsHostname = RoleEnvironment.GetConfigurationSettingValue("acsHostname");
trustedTokenPolicyKey = RoleEnvironment.GetConfigurationSettingValue("trustedTokenPolicyKey");
trustedAudience = RoleEnvironment.GetConfigurationSettingValue("trustedAudience");
}
catch
{
GenerateErrorResponse();
}
finally
{
}
} // end AccessControlServiceAuthorizationManager() Constructor
protected override bool CheckAccessCore(OperationContext operationContext)
{
String headerValue = WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Authorization];
String token = String.Empty;
string[] nameValuePair = null;
TokenValidator validator = null;
if (String.IsNullOrEmpty(headerValue))
{
GenerateErrorResponse();
return false;
}
if (!headerValue.StartsWith("WRAP "))
{
GenerateErrorResponse();
return false;
}
nameValuePair = headerValue.Substring("WRAP ".Length).Split(new char[] { '=' }, 2);
if (nameValuePair.Length != 2 ||
nameValuePair[0] != "access_token" ||
!nameValuePair[1].StartsWith("\"") ||
!nameValuePair[1].EndsWith("\""))
{
GenerateErrorResponse();
return false;
}
token = nameValuePair[1].Substring(1, nameValuePair[1].Length - 2);
validator = new TokenValidator(acsHostname, serviceNamespace, trustedAudience, trustedTokenPolicyKey);
if (!validator.Validate(token))
{
GenerateErrorResponse();
return false;
}
return true;
}
public void GenerateErrorResponse()
{
}
}
}
My Web.config is as follows;
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<behaviors>
<serviceBehaviors>
<behavior name="Secure">
<serviceAuthorization serviceAuthorizationManagerType="SecureService.AccessControlServiceAuthorizationManager" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="SecureService.Demo">
<endpoint address="" behaviorConfiguration="webBehavior" binding="webHttpBinding" bindingConfiguration="" contract="SecureService.IDemo" />
<endpoint address="rest" behaviorConfiguration="webBehavior" binding="webHttpBinding" bindingConfiguration="" contract="SecureService.IDemo" />
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</modules>
</system.webServer>
However the CheckAccessCore() method does not seem to be called when I call the service via IE. So the question is how can I ensure it is called and therefore ensure that my users are validated.
I have put a break point in the CheckAccessCore and it never seems to get hit.
And just to make things really interesting - I will need to call this webservice from within Silverlight.
Thanks in advance
Ignore your 'services' section in config. Try:
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint crossDomainScriptAccessEnabled="True" automaticFormatSelectionEnabled="true" helpEnabled="True"/>
</webHttpEndpoint>
</standardEndpoints>
Following the configuration pasted above, I see that service behavior "Secure" is missed to apply on Service. Please check it, if it's not a typo...