Error calling WCF webservice through channelfactory - not permissioned - c#

I am using a ChannelFactory to call into a WCF service (as the target service location will change depending on environment and I need the URL to be configurable). However I get the error:
The HTTP request is unauthorized with client authentication scheme
'Anonymous'. The authentication header received from the server was
'Negotiate,NTLM'.
My calling code
var myBinding = new BasicHttpBinding();
var myEndpoint = new EndpointAddress(webserviceAddress);
var myChannelFactory = new ChannelFactory<IObjectService>(myBinding, myEndpoint);
var serviceClient = myChannelFactory.CreateChannel();
My WCF service web.config system.servicemodel section
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" minFreeMemoryPercentageToActivateService="0" />
</system.serviceModel>
The service should be authenticated based on Windows Authentication. I would have thought by default the calling code above would use Windows Authentication to pass the account that the code is running as (a service account) but it seems to be sending anonymous

You must set the mode to transport with message credentials, as shown in the following code:
var myBinding = new BasicHttpBinding();
myBinding.Security.Mode = SecurityMode.TransportCredentialOnly;
As an alternative, you can set the mode in the constructor of the binding:
var myBinding = new BasicHttpBinding(SecurityMode.TransportCredentialOnly);
Also set the ClientCredential:
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

Related

Entity Famework Data Service as a Windows Service how to change maxReceivedMessageSize

I'm trying to increase the maxReceivedMessageSize for my DataService. I've tried the solutions from these places:
https://malvinly.com/2011/05/09/wcf-data-services-and-maxreceivedmessagesize/
How do I setup config files for WCF Data Service (odata) with EF 6
and some other places I can't remember but I can't get it working. The DataService is not running for a Web Application but in a Windows Service. The app.config is currently looking like this:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" bindingConfiguration="Test"/>
</protocolMapping>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
<basicHttpsBinding>
<binding name="Test" maxBufferSize="10485760" maxReceivedMessageSize="10485760">
<readerQuotas maxDepth="10485760" maxStringContentLength="10485760"
maxArrayLength="10485760" maxBytesPerRead="10485760" maxNameTableCharCount="10485760" />
</binding>
</basicHttpsBinding>
</bindings>
</system.serviceModel>
EDIT
I've updated the app.config content... Still can't figure out how this should be done.
EDIT
As recommended I've also set the readerQuotas without success
After a while we've found a solution...
Initially we took the DataServiceHost class to host our Service which does not support these options. After using WebServiceHost to host the service it worked:
WebServiceHost webServiceHost = new WebServiceHost(typeof(EfoDataService), new Uri[] { });
//Https binding
WebHttpBinding httpsbinding = new WebHttpBinding()
{
Security = { Mode = WebHttpSecurityMode.Transport },
MaxReceivedMessageSize = 2097152,
MaxBufferSize = 2097152,
MaxBufferPoolSize = 2097152,
TransferMode = TransferMode.Streamed
};
//adding https endPoint
webServiceHost.AddServiceEndpoint(typeof(IRequestHandler), httpsbinding, secureBaseAddress);
It's a bit strange though since DataServiceHost does derive from WebServiceHost.

WCF: Cant get my Web service to work, on the server

My issue is that i have this Webservice EService that works really great in my debug projekt, but when i implement it into a WinForm projekt, and put the service on a server. I get this error when crateing the client?
An unhandled exception of type 'System.InvalidOperationException'
occurred in System.ServiceModel.dll
Could not find default endpoint element that references contract '{0}' in the ServiceModel
client configuration section. This might be because no configuration file was found for your application,
or because no endpoint element matching this contract could be found in the client element.
App.config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IEService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://Domane.dk/EService.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IEService" contract="IEService"
name="BasicHttpBinding_IEService" />
</client>
Web.config
<system.serviceModel>
<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="basicHttpBinding" scheme="http" />
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<bindings>
<basicHttpBinding>
<binding name="" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" transferMode="Streamed">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
The way im calling it
using (var test = new EServiceAPI.EServiceClient())
{
test.OpdaterLeastDatoWinPLC(connstr);
}
I cant se the reason why it fails. Sorry for being such a newbi. And yes i've harvestet the internet for 2 days trying to find a solusion now.
I have had the same problem when using a web service in a dll.
Try this:
using (var test = CreateWebServiceInstance("http://url.to.mywebservice.com"))
{
test.OpdaterLeastDatoWinPLC(connstr);
}
Enter the correct url to the web service above and create the client using the code below. You still need to add the web service to the project so that the class EServiceClient is created for you.
internal static EServiceAPI.EServiceClient CreateWebServiceInstance(string url) {
BasicHttpBinding binding = new BasicHttpBinding();
binding.SendTimeout = TimeSpan.FromMinutes(10);
binding.OpenTimeout = TimeSpan.FromMinutes(1);
binding.CloseTimeout = TimeSpan.FromMinutes(1);
binding.ReceiveTimeout = TimeSpan.FromMinutes(20);
binding.AllowCookies = false;
binding.BypassProxyOnLocal = false;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.MessageEncoding = WSMessageEncoding.Text;
binding.TextEncoding = Encoding.UTF8;
binding.TransferMode = TransferMode.Buffered;
binding.UseDefaultWebProxy = true;
binding.MaxReceivedMessageSize = 5242880;
return new EServiceAPI.EServiceClient(binding, new EndpointAddress(url));
}
If it works you can modify the settings above to suit your needs better.
I think this has to do with the <endpoint address="http://Domane.dk/EService.svc" i believe it should be a relative path when using on a server.
Like:
<endpoint address="./EService.svc"

Pass Windows credentials to remote https WCF service

I need some help, I'm trying to pass windows credentials to a WCF service. In the IIS only Windows authentication is enabled for those service and runs over https.
The server side config is:
<system.serviceModel>
<protocolMapping>
<add scheme="https" binding="basicHttpBinding" bindingConfiguration="httpsBinding"/>
</protocolMapping>
<bindings>
<basicHttpBinding>
<binding name="httpsBinding">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
and in the client side:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://myserver.net:4343/MyService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService"
contract="MyServiceReference.IMyService" name="BasicHttpBinding_IMyService" />
</client>
I'm trying to consume the service on this way:
Client = new MyServiceClient();
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
binding.MaxReceivedMessageSize = int.MaxValue;
binding.MaxBufferPoolSize = long.MaxValue;
binding.MaxBufferSize = int.MaxValue;
EndpointAddress ep = new EndpointAddress("https://myserver.net:4343/MyService.svc");
Client = new COMINTSServiceClient(binding, ep);
Client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;
Client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
Client.Open();
Array[] obj = Client.RandomMethod();
This code doesn't work for me:
Client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;
Client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
In the service when ask for the user who is calling to the service using ServiceSecurityContext.Current.WindowsIdentity.Name allways get: ISS APPPOOL\ASP.NET v4.0 instead of the domain\user who is calling
The only way to make it work is write the username and password instead DefaultNetworkCredentials.
Client.ClientCredentials.Windows.ClientCredential.UserName = "DOMAIN\\user";
Client.ClientCredentials.Windows.ClientCredential.Password = "passw";
But I don't want a user/passw hardcoded.
Any help please?
Try:
Client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
Keep the assignment from CredentialCache.
I faced with similar issue - "ServiceSecurityContext.Current.WindowsIdentity.Name" on the server side returned wrong username, not Current Windows User on the client side. Turns out "Client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials" may get credentials from Windows Credential Manager:
I failed to find a solution to instruct WCF to avoid grabbing credentials from that storage. The workaround was to check if some credentials are stored for that IP address and remove them. I used "https://www.nuget.org/packages/CredentialManagement" for checking and removing. Here is the code:
var creds = new Credential();
creds.Type = CredentialType.DomainPassword;
creds.Target = address.Uri.Host;//address is WCF EndpointAddress
if (creds.Load() && creds.Username != System.Security.Principal.WindowsIdentity.GetCurrent().Name)
{
creds.Delete();
}

WCF client in a universal app

Is it possible to call a WCF service from a universal application?
I added a service reference and the proxy was generated just fine.
But when creating a NetTcpBinding programmatically and passing that to the proxy's constructor the service model throws the exception PlatformNotSupported.
Both running the app in the simulator and on the local machine generates the same exception.
An exception of type 'System.PlatformNotSupportedException' occurred
in System.Private.ServiceModel.dll but was not handled in user code
"this operation is not supported"
EndpointAddress address = new EndpointAddress("net.tcp://test:9000/ServicesHost/PublishService");
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
PublishingService.PublishClient proxy = new PublishingService.PublishClient(binding, address);
Does anybody have an example of a working WCF client in a UAP?
EDIT
It has something to do with the service being a duplex service!
The original contract:
[ServiceContract(CallbackContract = typeof(IPublishCallback))]
public interface IPublish { }
After removing the CallbackContract attribute the UAP client can create a connection, so basic WCF works.
So I guess it's better to rephrase the question.
Is it possible to create a duplex WCF client in a universal application?
edit servicemodel for the host
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTcpPublishService" openTimeout="00:00:10" receiveTimeout="infinite">
<reliableSession inactivityTimeout="24.20:31:23.6470000" enabled="true" />
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehaviour">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="serviceBehaviour" name="PublishService.Publish">
<endpoint binding="mexHttpBinding" name="mexPublishService"
contract="IMetadataExchange" />
<endpoint address="PublishService" binding="netTcpBinding" bindingConfiguration="netTcpPublishService"
name="netTcpPublishService" contract="PublishService.IPublish" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8004/ServicesHost/PublishService" />
<add baseAddress="net.tcp://localhost:9004/ServicesHost/PublishService" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
Yes, it is possible. This is how i connect in a sample app i did a while ago:
using Tradeng.Srvc.Client.WinAppSimple.SrvcRefTradeng;
private InstanceContext instanceContext;
private TradengSrvcClientBase serviceProxy;
instanceContext = new InstanceContext(this);
serviceProxy = new TradengSrvcClientBase(instanceContext);
bool result = await serviceProxy.ConnectAsync();
if (result)
{
// connected...
}
I used the binding from the config file that is generated when you add a reference to your service.
This is what the app looks like. Cutting edge stuff.... :O)
https://www.youtube.com/watch?v=YSg6hZn1DpE
The service itself is running as a WebRole on Azure, by the way.

Validate Oauth Access Token in WCF Message Inspector

I have a client (could be C# or PHP) that needs to be able to request an OAuth 2.0 access token (JWT for compatibility) from my STS (Thinktecture Identity Server), and then send that token to a webhttp endpoint in a WCF Service. The service will validate the token in a message inspector, and either throw an error or continue to a service method. I am using Thinktecture Identity Model, and RestSharp to send rest requests.
So far here is what I have:
Client:
var client = new OAuth2Client(
new Uri("https://mysts/issue/oauth2/token"),
"client",
"secret");
var response = client.RequestAccessTokenUserName("username", "password", "http://localhost:51696/");
var token = response.AccessToken;
var restClient = new RestClient("https://127.0.0.1:444/");
var restRequest = new RestRequest(Method.POST);
restRequest.AddHeader("Authorization", token);
restRequest.AddObject(new Request());
And I get the access token from the sts just fine, I'm not sure if I'm inserting the token in the authorization header correctly or not.
Message inspector:
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
#region new code
string binding = OperationContext.Current.EndpointDispatcher.ChannelDispatcher.BindingName;
if (binding == "http://tempuri.org/:SecureRestBinding")
{
// Check to see if there is an Authorization in the header, otherwise throw a 401
if (WebOperationContext.Current.IncomingRequest.Headers["Authorization"] == null)
{
WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;
WebOperationContext.Current.OutgoingResponse.Headers.Add("WWW-Authenticate: Basic realm=\"myrealm\"");
throw new WebFaultException<string>("No username or password was provided", HttpStatusCode.Unauthorized);
}
else
{
//Code to validate oauth token?
}
}
This makes sure to only check REST messages, SOAP messages are handled via a security token handler. I need to fill in code to validate the oauth token, but I cant seem to find a good example anywhere.
web.config in case its relevant:
<system.serviceModel>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="MyWCFWebRole.MyWcfService">
<endpoint address="/REST/"
behaviorConfiguration="MyRestBehavior"
binding="webHttpBinding" bindingConfiguration="RESTSSLBinding"
name="RestSSLEndpoint" bindingName="SecureRestBinding"
contract=MyWCFWebRole.MyWcfServic" />
<endpoint address="/SOAP/"
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
name="SecureHttpEndpoint"
bindingName="SecureHttpBinding"
contract="MyWCFWebRole.MyWcfServic" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="RESTSSLBinding">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
<ws2007FederationHttpBinding>
<binding name="">
<security mode="Message">
<message>
<issuerMetadata address="mex_address" />
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="MyRestBehavior">
<webHttp helpEnabled="true" faultExceptionEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization principalPermissionMode="Always" />
<serviceCredentials useIdentityConfiguration="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment minFreeMemoryPercentageToActivateService="0" aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<protocolMapping>
<add scheme="http" binding="ws2007FederationHttpBinding" />
</protocolMapping>
</system.serviceModel>
<system.webServer>
<defaultDocument>
<files>
<clear />
<add value="MyService.svc" />
</files>
</defaultDocument>
<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="false" />
</system.webServer>
Any help is appreciated. Using .net 4.5

Categories

Resources