WCF REST/JSON Service UserNamePasswordValidator - asp.net

I'm trying to use basic authentication with my WCF Rest/JSON service.
Therefore I've create a class which derives from "UserNamePasswordValidator" and added it to my web.config.
In IIS only Basic Authentication is enabled.
Unfortunately this class is never called. When I call a rest method in my browser the dialog for entering the username and password is shown but nothing happens after that.
Here my web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext"
value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<identity impersonate="true" />
</system.web>
<system.serviceModel>
<services>
<service name="myTimeMvc.Webservice.MyTimeRestService"
behaviorConfiguration="returnFaults">
<endpoint behaviorConfiguration="restfulBehavior"
binding="webHttpBinding"
bindingConfiguration="webBinding"
contract="myTimeMvc.Webservice.IMyTimeRestService" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="restfulBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="returnFaults">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<serviceCredentials>
<!--<serviceCertificate findValue="MyWebSite"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />-->
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="myTimeServiceDemoa.WcfExtension.CustomUserNameValidator,TestWcfServiceAuth" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true" />
<validation validateIntegratedModeConfiguration="false" />
</system.webServer>
</configuration>
Here my CustomUserNameValidator.cs
namespace myTimeServiceDemoa.WcfExtension
{
public class CustomUserNameValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException("You must provide both the username and password to access this service");
}
if (!(userName == "user1" && password == "test") && !(userName == "user2" && password == "test"))
{
throw new FaultException("Unknown Username or Incorrect Password");
}
}
}
}
UPDATE:
After two days of trying I give up now because I don't see what I may have done wrong. Seems this stuff is not working for me...
I investigated a lot and everything you need is to change Authentication of your WebApplication in IIS to "Basic" and add a custom "CustomUserNameValidator" in your web.config but this is not working!
Please correct me if I'm wrong.
My solution:
Use "Anonymous Authentication" in IIS
Use a "ServiceAuthorizationManager" and check HTTP-Headers in "CheckAccessCore"
Cheers,
Stefan

Related

wcf 400 bad requset error

i am having this issue and i looked in all the web and saw lots of answers but nothing helped me
my issue is that i every time i make get from the wcf service its 400 bad request
but when i run the wcf test client it works fine
i am using vs 2015
my config file (which vs generated automatically )
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<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>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IProductService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8733/Design_Time_Addresses/Test/Service1/"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IProductService"
contract="ServiceReference.IProductService" name="BasicHttpBinding_IProductService" />
</client>
<services>
<service name="Test.ProductService">
<endpoint address="" binding="basicHttpBinding" contract="Test.IProductService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Design_Time_Addresses/Test/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<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>
</system.serviceModel>
<connectionStrings>
<add name="modelEntities" connectionString="metadata=res://*/Products.csdl|res://*/Products.ssdl|res://*/Products.msl;provider=System.Data.SqlClient;provider connection string="data source=localhost;initial catalog=test;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
and the service is
public interface IProductService
{
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json,UriTemplate = "/GetProducts")]
List<Product> GetProducts();
}
and this is the impplement method
public List<Product> GetProducts()
{
modelEntities context = new modelEntities();
var productEntity = (from p in context.productEntities select p);
List<Product> products = new List<Product>();
foreach (var item in productEntity)
{
products.Add(TranslateProductEntityToProduct(item));
}
return products;
}
i was trying without the webinvoke
also tried webget
and also try to replace the basichttpbinding with webbinding
and also look for many answers here and on the net and nothing helped me
hope you an help me
Thanks

How can I host a WCF service without an SVC file in IIS

I'd like to deploy a dual interface (SOAP/REST/XML/JSON) WCF service in IIS with just a config file and the binaries and no svc file in the URL
We use VS2012 and .Net 4.5
We have something like it working, I followed a guide here:
http://blogs.msdn.com/b/rjacobs/archive/2010/04/05/using-system-web-routing-with-data-services-odata.aspx
I added a Global class with
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
private void RegisterRoutes()
{
DataServiceHostFactory factory = new DataServiceHostFactory();
RouteTable.Routes.Add(new ServiceRoute("wrap", factory, typeof(NeOtheWrapper)));
}
}
And I used my existing web.config which defines all the endpoints:
<system.serviceModel>
<!-- Clients -->
<client>
<endpoint name="MySoftLive" address="https://backof.somewebsitett.com/Cmp.MySoft.bl/MySoft.svc" binding="basicHttpsBinding" bindingConfiguration="soapSecureBindingConfig" contract="Cmp.MySoft.BL.WCF.MySoftInterface" />
<endpoint name="MySoftTest" address="http://localhost:49957/MySoft.svc" binding="basicHttpBinding" bindingConfiguration="soapBindingConfig" contract="Cmp.MySoft.BL.WCF.MySoftInterface" />
</client>
<!-- Services -->
<services>
<service name="Cmp.MySoft.BL.NeOthe.NeOtheWrapper">
<endpoint name="rest" address="rest" behaviorConfiguration="restEndpointBehaviour" binding="webHttpBinding" bindingConfiguration="restBindingConfig" contract="Cmp.MySoft.BL.NeOthe.INeOtheWrapper"/>
<endpoint name="restSecure" address="rest" behaviorConfiguration="restEndpointBehaviour" binding="webHttpBinding" bindingConfiguration="restSecureBindingConfig" contract="Cmp.MySoft.BL.NeOthe.INeOtheWrapper"/>
<endpoint name="mex" address="mex" behaviorConfiguration="" binding="mexHttpBinding" bindingConfiguration="mexBindingConfig" contract="Cmp.MySoft.BL.NeOthe.INeOtheWrapper"/>
<endpoint name="mexSecure" address="mex" behaviorConfiguration="" binding="mexHttpsBinding" bindingConfiguration="mexSecureBindingConfig" contract="Cmp.MySoft.BL.NeOthe.INeOtheWrapper"/>
<endpoint name="soap" address="soap" behaviorConfiguration="" binding="basicHttpBinding" bindingConfiguration="soapBindingConfig" contract="Cmp.MySoft.BL.NeOthe.INeOtheWrapper"/>
<endpoint name="soapSecure" address="soap" behaviorConfiguration="" binding="basicHttpsBinding" bindingConfiguration="soapSecureBindingConfig" contract="Cmp.MySoft.BL.NeOthe.INeOtheWrapper"/>
</service>
</services>
<!-- Binding Configurations -->
<bindings>
<webHttpBinding>
<binding name="restBindingConfig">
<security mode="None"/>
</binding>
<binding name="restSecureBindingConfig">
<security mode="Transport"/>
</binding>
</webHttpBinding>
<mexHttpBinding>
<binding name="mexBindingConfig"/>
</mexHttpBinding>
<mexHttpsBinding>
<binding name="mexSecureBindingConfig"/>
</mexHttpsBinding>
<basicHttpsBinding>
<binding name="soapSecureBindingConfig">
<security mode="Transport"/>
</binding>
</basicHttpsBinding>
<basicHttpBinding>
<binding name="soapBindingConfig">
<security mode="None"/>
</binding>
</basicHttpBinding>
</bindings>
<!-- Behaviour Configurations -->
<behaviors>
<endpointBehaviors>
<behavior name="restEndpointBehaviour">
<webHttp helpEnabled="true" defaultBodyStyle="Bare" defaultOutgoingResponseFormat="Json" automaticFormatSelectionEnabled="true" faultExceptionEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</serviceBehaviors>
</behaviors>
<!-- Hosting Environment Settings -->
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
</system.serviceModel>
It compiles, runs and if I browse to http://mypc:12345/wrap/rest/help I get the auto generated ASP.NET REST help page.
But, if I go to http://mypc:12345/wrap/soap/ I get 400 Bad Request.
I can't suffix that with ?wsdl to get the wsdl, or pass the url to svcutil (soap+xml not expected)
I was hoping the .SVC SOAP place holder page would appear, same as /help does for REST.
If I browse to the .svc file (it's at the same level as /wrap) that works and the soap service works, as does meta data publishing.
Am I using the wrong URL or is my configuration wrong?
If you're using WCF 4.0 or later, you can use "file-less" activation. Add something like the following to config your file:
<serviceHostingEnvironment multipleSiteBindingsEnabled="true">
<serviceActivations>
<add factory="System.ServiceModel.Activation.ServiceHostFactory"
relativeAddress="Soap.svc"
service="Cmp.MySoft.BL.NeOthe.NeOtheWrapper" />
</serviceActivations>
</serviceHostingEnvironment>
This allows you to host a WCF service without a physical .svc file. The relativeAddress is relative to the base address of the site, and you'll need to create the IIS application as usual.
See the "File-Less activation" section in A Developer's Introduction to Windows Communication Foundation 4 for more information.

How to host workflow service (.xamlx) with net.tcp binding on IIS 7.0?

I am hosting Workflow service on iis 7.0 with net.tcp binding. My config file like as
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<appSettings>
<add key="SMTPAddress" value="000.00.0.00"/>
<add key="ToAddress" value="abc#abc.com"/>
<add key="FromAddress" value="abc#abc.com"/>
<add key="SMTPUserName" value="abc#abc.com"/>
<add key="SMTPPassword" value ="abc#abc.com"/>
</appSettings>
<connectionStrings>
<add name="RewindConnectionString" connectionString="Data Source=xxx;User Id=xxx;Password=xxx;Connection Timeout=5" providerName="Oracle.DataAccess.Client" />
</connectionStrings>
<system.serviceModel>
<tracking>
<profiles>
<trackingProfile name="Sample Tracking Profile">
<workflow activityDefinitionId="*">
<workflowInstanceQueries>
<workflowInstanceQuery>
<states>
<state name="*"/>
</states>
</workflowInstanceQuery>
</workflowInstanceQueries>
<activityStateQueries>
<activityStateQuery activityName="*">
<states>
<state name="*"/>
</states>
<variables>
<variable name="*"/>
</variables>
</activityStateQuery>
</activityStateQueries>
<activityScheduledQueries>
<activityScheduledQuery activityName="*" childActivityName="*"/>
</activityScheduledQueries>
<faultPropagationQueries>
<faultPropagationQuery faultSourceActivityName="*" faultHandlerActivityName="*"/>
</faultPropagationQueries>
<customTrackingQueries>
<customTrackingQuery name="*" activityName="*"/>
</customTrackingQueries>
</workflow>
</trackingProfile>
</profiles>
</tracking>
<services>
<service name="RewindTest" behaviorConfiguration="RewindTest_Behavior">
<endpoint address="RewindTest"
binding="netTcpBinding" contract="IRewindTestService" name="RewindTestNetTcpEndPoint" bindingConfiguration="RewindTestBinding" />
<endpoint address="wce"
binding="netTcpBinding" kind="workflowControlEndpoint" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:9095/Service.Workflow.RewindTest/RewindTest" />
</baseAddresses>
</host>
<endpoint address="mex"
binding="mexTcpBinding"
name="MEX"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding portSharingEnabled="true" name="RewindTestBinding" closeTimeout="00:10:00" openTimeout="00:10:00"
sendTimeout="00:10:00" maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<standardEndpoints>
<workflowControlEndpoint>
<standardEndpoint/>
</workflowControlEndpoint>
</standardEndpoints>
<extensions>
<behaviorExtensions>
<add name="oracleInstanceStore" type="Devart.Data.Oracle.Activities.Configuration.OracleInstanceStoreElement, Devart.Data.Oracle.WorkflowFoundation" />
<add name="oracleTracking" type="Devart.Data.Oracle.Activities.Configuration.OracleTrackingElement, Devart.Data.Oracle.WorkflowFoundation" />
</behaviorExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<behavior name="RewindTest_Behavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="false"/>
<!-- 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"/>
<oracleTracking
connectionString="User Id=xxx;Password=xxx;Server=xxx;"
profileName="Sample Tracking Profile" />
<oracleInstanceStore
connectionString="User Id=xxx;Password=xxx;Server=xxx;"
instanceEncodingOption="None"
instanceCompletionAction="DeleteNothing"
instanceLockedExceptionAction="NoRetry"
hostLockRenewalPeriod="00:00:30"
runnableInstancesDetectionPeriod="00:00:05" />
<workflowIdle timeToUnload="0"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Now my issue is i am unable to generate proxy through net.tcp binding but i can generate it through http. http://testsrv.com/RewindService/RewindTest.xamlx?wsdl. then i am unable to call receive operation method. Although it is workking fine with local console Host.
As we know that workflow service is similar to wcf service. So I decided to reconsider my deployment steps. I found a very good link about it and follow and check each and every step carefully and able to resolved my problem.
http://galratner.com/blogs/net/archive/2010/10/08/setting-up-a-nettcpbinding-enabled-wcf-service-in-iis-7.aspx
My configuration is ok and updated the tcp port no. it works like a charm.

WCF Session ASP.NET Hosting Issue

I am building a WCF service that speaks to an existing application, and this application requires access to ASP.NET sessions - the ability to see sessions is a requirement I cannot get around.
I built the WCF project - and have the following setting in App.config:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
I also included an interface and an implementation of the service in the file. In front of the implementation I have:
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Required)]
public class SearchService : ISearchServiceInterface
{
This is a REST service, so my interface starts like:
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface ISearchServiceInterface
{
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
string LoginToWebService_POST(Altec.Framework.Authorization auth);
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
string GetTopLevelFolderName_POST();
The service itself is hosted in another web application - in a SearchService.svc file which has this:
<%#ServiceHost language=c# Debug="true" Service="Altec.UI.Web.SearchService.SearchService" %>
and I added this to the web.config of the hosting application:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
I believe I did all the right steps - and yet when I try to run the web application I get this error:
"
System.InvalidOperationException: This service requires ASP.NET
compatibility and must be hosted in IIS. Either host the service in
IIS with ASP.NET compatibility turned on in web.config or set the
AspNetCompatibilityRequirementsAttribute.AspNetCompatibilityRequirementsMode
property to a value other than Required. at
System.ServiceModel.Activation.AspNetEnvironment.ValidateCompatibilityRequirements(AspNetCompatibilityRequirementsMode
compatibilityMode) at
System.ServiceModel.Activation.AspNetCompatibilityRequirementsAttribute.System.ServiceModel.Description.IServiceBehavior.Validate(ServiceDescription
description, ServiceHostBase serviceHostBase) at
System.ServiceModel.Description.DispatcherBuilder.ValidateDescription(ServiceDescription
description, ServiceHostBase serviceHost) at
System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription
description, ServiceHostBase serviceHost) at
System.ServiceModel.ServiceHostBase.InitializeRuntime() at
System.ServiceModel.ServiceHostBase.OnBeginOpen() at
System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) at
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan
timeout) at System.ServiceModel.Channels.CommunicationObject.Open()
at Microsoft.Tools.SvcHost.ServiceHostHelper.OpenService(ServiceInfo
info)"
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<appSettings>
<!-- database connection details -->
</appSettings>
<system.web>
<customErrors mode="Off"/>
<compilation debug="true">
<assemblies>
<add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
<pages>
<controls>
<add tagPrefix="ajaxToolkit" assembly="AjaxControlToolkit" namespace="AjaxControlToolkit"/>
</controls>
</pages>
</system.web>
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="1048576"/>
</webServices>
</scripting>
</system.web.extensions>
<location path="Scripts">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<location path="Content">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<location path="jQuery-UI-layout.css">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<!-- 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>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ISearchServiceInterface" 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" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://vmwarren27dev.altec-wa.com/Altec.UI.Web.Portal/SearchService.svc/WCPService" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISearchServiceInterface" contract="SearchService.ISearchServiceInterface" name="WSHttpBinding_ISearchServiceInterface">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
</client>
<services>
<service name="Altec.UI.Web.SearchService.SearchService">
<endpoint address="RESTService" binding="webHttpBinding" behaviorConfiguration="json" contract="Altec.UI.Web.SearchService.ISearchServiceInterface">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="WCPService" binding="wsHttpBinding" contract="Altec.UI.Web.SearchService.ISearchServiceInterface">
<identity>
<dns value="localhost"/>
</identity>
</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="True"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="json">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="AjaxControlToolkit" publicKeyToken="28f01b0e84b6d53e" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.1.51116.0" newVersion="4.1.51116.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
You mentioned App.config - it sounds like your service is a WCF Service Library, that you're hosting under IIS. If that's the case, you need to copy the WCF configuration section from the App.config to the Web.config of the IIS application that is hosting your service.
Libraries don't use config files - they use the config file of the calling application.

Authentication/Impersonation issue with ASP.NET call to WCF Service

I have a web page that calls a WCF service that makes a sql database call using Integrated Security. I get an error saying, "Login failed for user 'CorpDomain\ServerName01$'". I want it so that it all layers will execute under the user's AD credetials (working in an intranet), ie: "CorpDomain\Albert".
On the server (Win 2008/IIS 7), I have Windows Authentication turned on and everything else off (including Anonymous) under Authentication for both the web client and the WCF service.
Here's my client web.config:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<authentication mode="Windows"/>
<identity impersonate="true"/>
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IMyService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" 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://myurladdress/MyServices/Service.svc"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IMyService"
contract="MySvc.IMyService" name="NetTcpBinding_IMyService" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="ClientUserNameBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Here's my WCF service web.config:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="Windows"/>
<identity impersonate="true"/>
</system.web>
<connectionStrings>
<!--DB CONNECTION-->
<add name="myDB" connectionString="Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Carbon;Data Source=mydbname,10600" providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.serviceModel>
<services>
<service name="WCFServices.MyService" behaviorConfiguration="MyServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8000/WCFServices/MyService"/>
</baseAddresses>
</host>
<endpoint address="" binding="netTcpBinding" contract="WCFServices.IMyService" bindingConfiguration="tcpWindowsSecurity" bindingNamespace="http://WCFServices.MySvc/"/>
<endpoint address="MEX" binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization impersonateCallerForAllOperations="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="tcpWindowsSecurity" maxReceivedMessageSize="524288" maxBufferSize="524288">
<!--<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" protectionLevel="None" />
</security>-->
</binding>
</netTcpBinding>
</bindings>
<!--<serviceHostingEnvironment multipleSiteBindingsEnabled="true" >-->
<serviceHostingEnvironment >
<serviceActivations>
<add relativeAddress="~/MyService.svc" service="WCFServices.MyService"/>
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
on the client side:
Request.ServerVariables["AUTH_USER"].ToString() = "CorpDomain\Albert"
Page.User.Identity.Name = "CorpDomain\Albert"
System.Threading.Thread.CurrentPrincipal.Identity.Name = "CorpDomain\Albert"
System.Security.Principal.WindowsIdentity.GetCurrent().Name = "NT AUTHORITY\NETWORK SERVICE"
My client code is basically:
MySvc.MyServiceClient svc = new MySvc.MyServiceClient();
svc.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
Response.Write(svc.GetServiceHtml());
and on the WCF side:
ServiceSecurityContext.Current.WindowsIdentity.Name = "NT AUTHORITY\NETWORK SERVICE"
server side code is:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string GetServcieHtml()
{
string name, link;
StringBuilder html = new StringBuilder();
html.Append(ServiceSecurityContext.Current.WindowsIdentity.Name);
try
{
using (SqlConnection conn = GetDataConnection())
{
conn.Open();
SqlCommand sqlcom = new SqlCommand("dbo.runsomeproc", conn);
sqlcom.CommandType = CommandType.StoredProcedure;
SqlDataReader sqlDataReader = sqlcom.ExecuteReader();
while (sqlDataReader.Read())
{
// ** SOME CODE HERE **
}
conn.Close();
}
}
catch (Exception ex)
{
html.AppendLine("<br><br>ERROR:" + ex.Message + " " + ex.InnerException);
return html.ToString();
}
return html.ToString();
}
Note:
The error I get is: ERROR:Login failed for user 'CorpDomain\ServerName01$'.
Any idea what I'm doing wrong?
Also, correct me if I'm wrong, but in your client web.config, you have a behaviour that will set impersonation level to "Impersonation", but you do not reference that behaviour in your endpoint. Eg:
<client>
<endpoint address="net.tcp://myurladdress/MyServices/Service.svc"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IMyService"
contract="MySvc.IMyService" name="NetTcpBinding_IMyService" />
</client>
Should be:
<client>
<endpoint address="net.tcp://myurladdress/MyServices/Service.svc"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IMyService"
contract="MySvc.IMyService" name="NetTcpBinding_IMyService"
behaviorConfiguration="ClientUserNameBehavior" />
</client>
You also need to enable impersonation at the WCF service level as well.
This MSDN page contains all the details.
I don't know if this will help anyone, but I had this problem. The problem was due to the identity setting of the Application Pool that my service was using in IIS. If you set the appropriate identity there, you should be good. In my case, the default was set to NT Authority\Network Service.

Resources