Impersonation error when calling wcf-service - wcf

I developed a wcf service. Since it will also be called by non-.net clients, I used basichttpbinding. Some of the methods need Impersonation. This is forced by decorating the webmethods with:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
After I deployed the service on our test server, I get a strange error when I call the service:
Could not load file or assembly 'log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821' or one of its dependencies. Either a required impersonation level was not provided, or the provided impersonation level is invalid. (Exception from HRESULT: 0x80070542)
I get this error independently of the way I call the service. I get it when I call it via wcfTestClient and I get it when I call it via a console application that I wrote. (I added the webservice as web reference to this application to simulate the behaviour of a non .net client.)
Any ideas?
PS: Here is the web.config of my webservice:
<system.web>
<compilation targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding closeTimeout="00:15:00" openTimeout="00:15:00" sendTimeout="00:15:00" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<defaultDocument>
<files>
<add value="CrmConnectorDiamondData.svc" />
</files>
</defaultDocument>
</system.webServer>
</configuration>

Well in WCF client must allow impersonation explicitly. In WCF client it is done by adding behavior to client proxy either through configuration:
<behaviors>
<endpointBehaviors>
<behavior name="myBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
Or in the code:
proxy.ClientCredentials.Windows.AllowImpersonationLevel = TokenImpersonationLevel.Impersonation;
I expect that this have to be configured for WcfTestClient because default impersonation level allows only idnetification.
In case of ASMX proxy make sure that you are passing your credentials.
My opinion is that windows authentication is not a good choice for services used by non-.NET clients (especially if you also mean non-Windows).

Looks like the log4net library is incompatable with that impersonation level. If you remove the reference it will work.

Related

New WCF web service returns 401 in one environment

We recently deployed a WCF web service to our prod environment. Attempts to call it or even access the WSDL from a browser return a 401. Where would this authentication be happening?
This service sits in its own virtual application under a website with a dozen other similar services. These do not exhibit the same symptoms. Similarly, this did not occur on any of three pre-prod environments.
I've looked through IIS settings on the virtual app and the application pool but nothing stands out to me. The only discrepancy I see between the UAT and Production configs is the prod one targets 4.6.1 instead of 4.6.2.
Web.config from prod:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1" />
<customErrors mode="Off" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding maxReceivedMessageSize="40000000">
</binding>
</basicHttpBinding>
<basicHttpsBinding>
<binding maxReceivedMessageSize="40000000">
</binding>
</basicHttpsBinding>
</bindings>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" />
</system.webServer>
</configuration>
Does anyone have an idea why this one site would be bouncing connections as unauthorized--even when just browsing to hit the wsdl?
UPDATE
After thinking and checking here, I found the sub-status code being
returned was 3, indicating permissions on the folder. Adding everyone (temporarily) fixed the issue. This still leaves trying to track down why a virtual app under the same site as many others, using the same account to run the app pool as all other app pools experienced this issue.
I don’t know how do you configure during the deploy/publish process. On my side, I have made a simple demo, it works normally.I would like that you could share more details about your project.
Server(configuration)
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpsBinding>
<binding maxReceivedMessageSize="40000000">
</binding>
</basicHttpsBinding>
</bindings>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Server(interface/class).
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
My server environment (10.157.13.70) is win10, IIS10. virtual path is C:\Test.
Here is what I have done in IIS.
Add the https binding and development certificate.
Besides, I have the Anonymous Authentication enable in IIS authentication module(default settings).
WCF feature.
Result.
Feel free to let me know if the problem still exists.

Cannot connect to a WCF service with application, but can with SOAPUI

I'm trying to consume a WCF service, hosted in a shared server. it works perfectly with SOAPUI, but when i tried to do it with my vb.net application it give me this error:
the http request is unauthorised with client authentication scheme
"anonymous".
I tried a lot of solutions, changing the app.config of my application, adding security mode="TransportCredentialOnly", with clientCredentialType="Windows" and "NTLM", and it only changes the last part of the error, giving "Negotiate" with "anonymous".
here how i add security in app.config
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
I think this is an application problem because, as I said before, it works perfectly in SOAPUI, I don't know if I need to add something more.
The web.config of WCF:
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<httpRuntime maxRequestLength ="262144" executionTimeout="103600"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32"
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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<httpErrors errorMode="Detailed"/>
</system.webServer>
EDIT:
I just receive an answer from server's provider and he said that there's a program, ModSecurity, that is blocking me access to WCF until i add a correct content header and user agent. How can i add it to the call?
UPDATE:
I used the answer of GMan80013 and now i'm stuck in this part.
I'm getting this error "Coul not load type 'Microsoft.ServiceModel.Dispatcher.HttpUserAgentBehaviorExtensionElement, SolutionPruebas.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' registered for the extension 'httpUserAgent'".
This error come from this part, I assume:
<behaviorExtensions>
<add name="httpUserAgent" type="Microsoft.ServiceModel.Dispatcher.HttpUserAgentBehaviorExtensionElement, SolutionPruebas.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</behaviorExtensions>
Or from here.
<behaviors>
<endpointBehaviors>
<behavior name="LegacyServiceEndpointBehavior">
<httpUserAgent userAgent="test user agent" />
</behavior>
</endpointBehaviors>

WCF REST communication with Windows Phone

I'm having some trouble regarding a rest request sent from my Windows Phone app via RestSharp to a self hosted WCF service I have made. The request works fine in the emulator and the request returns a result but when I try to perform the request on my app on an actual device it fails and the request does not return anything.
Having done a fair amount of research I have discovered that apparently webHttpBinding is not supported on Windows Phone and therefore I need to add a basicHttpBinding endpoint to my Web.config file. However, when I try to do this I get several errors associated with having more than one endpoint and I can't seem to get any solution to successfully work with both of these. Switching the endpoint to basicHttpBinding and commenting out webHttpBinding also causes an error when I navigate to localhost:81/mywebservice.svc
"System.InvalidOperationException: For request in operation analyseFace to be a stream the operation must have a single parameter whose type is Stream."
asking for the stream that should be attached with a request. It shows a normal help page using the original code and the same address.
My web.config file
<trace>
<listeners>
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="AzureDiagnostics">
<filter type="" />
</add>
</listeners>
</trace>
</system.diagnostics>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</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>
<behavior name="servicebehavior">
<!--<serviceMetadata httpGetEnabled="true"/>-->
<serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="restbehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="servicebehavior" name="VizageAPIWebRole.vizage">
<endpoint address="" behaviorConfiguration="restbehavior" binding="webHttpBinding" name="RESTEndPoint" contract="VizageAPIWebRole.Ivizage" />
<!--<endpoint address="" binding="basicHttpBinding" contract="VizageAPIWebRole.Ivizage" />-->
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
<webHttpBinding>
<binding name="RestBinding">
<readerQuotas maxStringContentLength="5242880" maxArrayLength="16384" maxBytesPerRead="4096" />
<security mode="None">
</security>
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
My WCF SERVICE
[ServiceContract]
public interface Ivizage
{
[WebInvoke(UriTemplate = "/agerecog/{auth}", Method = "POST")]
VizageResult analyseFace(string auth, Stream dataStream);
}
I'm wondering if someone can help me work out what code I have to edit in my web.config to make this work for both endpoints as I haven't had any luck so far with things I've tried
Your code seems to be a REST service, but basicHttpBinding supports SOAP. So please continue to use webHttpBinding. However, on the Windows Phone side, the WCF cannot be used, it is needed to use WebClient or HttpWebRequest to access a REST service. WCF can just help us to access a SOAP service.
In addition, you mentioned the application works fine in the emulator, so it is unlikely to be a coding issue. It would be better if you can check whether your real phone device is able to access internet. Please also make sure you're using the cloud service's address instead of 127.0.0.1. Local address will not work on a real device.
Best Regards,
Ming Xu.
From the exception and your config - you are using simplified configuration which by default uses basicHttpBinding. You have to explicity define service end point
<services>
<service name="WcfRest.Ivizage">
<endpoint behaviorConfiguration="restbehavior" binding="webHttpBinding"
contract="WcfRest.Ivizage" />
</service>
</services>
Edit: looks like webHttp is not supported

svcutil doesn't generate config file

I have wcf service. I tried to generate proxy code and configuration file for client program by svcutil:
svcutil http://localhost/WcfService2/Files.svc
I got valid file with proxy, but didn't get config file. Why?
(VS2010 SP1, .NET 4.0, IIS 7.0)
My service contract:
[ServiceContract]
public interface IFiles
{
[OperationContract]
Guid UploadFile(Stream stream);
}
My web config:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="WebHttpBinding" maxBufferSize="65536" maxBufferPoolSize="524288"
maxReceivedMessageSize="1073741824" transferMode="Streamed" />
</webHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="WcfService2.Files">
<endpoint behaviorConfiguration="WebHttpBehavior" binding="webHttpBinding"
bindingConfiguration="WebHttpBinding" name="Files" contract="WcfService2.IFiles" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WebHttpBehavior">
<webHttp defaultBodyStyle="Wrapped" defaultOutgoingResponseFormat="Json"
automaticFormatSelectionEnabled="false" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.web>
<httpRuntime maxRequestLength="100000" />
</system.web>
</configuration>
Endpoints which use the WebHttpBinding (a.k.a., WCF WebHttp endpoints), do not expose metadata like "normal" (i.e., SOAP) endpoints do. WCF will still generate a WSDL for your service (since you specified <serviceMetadata httpGetEnabled="true"/>), but the metadata will only contain certain aspects of the service (such as data contracts, etc). The Web-related features (WebInvoke/WebGet attributes) won't be on the proxy, so even though you get a proxy file, you'll likely won't be able to use it to communicate to the service (unless you didn't use any of those). The problem is that there's no widely accepted format for describing metadata for REST services (WADL is possibly the most used, but it's not nearly as prevalent as WSDL for SOAP, and it's not implemented by WCF).
In short: svcutil doesn't really work for web endpoints.
If you want the long version: http://blogs.msdn.com/b/carlosfigueira/archive/2012/03/26/mixing-add-service-reference-and-wcf-web-http-a-k-a-rest-endpoint-does-not-work.aspx

Configure WCF to ignore authentication requirements inside IIS

Scenario:
Two websites (example.com, admin.example.com) that share the same wwwroot folder.
example.com allows only anonymous access
admin.example.com allows only windows authentication.
/Service/Awesome.svc returns a json object
Accessing the Awesome service using example.com works, while admin.example.com throws a NotSupportedException; "Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service."
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="WcfServices.AwesomeService"
behaviorConfiguration="serviceBehavior">
<endpoint address="" binding="webHttpBinding"
contract="WcfServices.IAwesomeService"
behaviorConfiguration="jsonBehavior" />
</service>
</services>
</system.serviceModel>
How do I configure WCF to ignore the authentication requirement? I want the same behavior as if this were a web service or handler, just execute and return the awesome json object.
I think you're out of luck here. Give AWesome.svc anonymous access, and give anon access a user account that has no access to sensitive resources.
It sounds like you have two copies of the service, one under the website example.com and the other under admin.example.com. If admin.example.com needs IIS integrated (challenge/response) authentication then you're WCF service binding needs to be in Transport mode because IIS requires all admin.example.com resources to be Windows authentication. Try this configuration:
<bindings>
<basicHttpBinding>
<binding name="Binding1">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
If this doesn't work for you, you may want to try hosting the services in their own virtual directy so they are not at the mercy of what the website needs for security.
Good Luck.