Calling a SAP ME web Service in wcf web service - c#

I have a soap web service (sap me web service), I generated the wcf proxy. no problem, I developed a WinForms application no problem
Now i try to use it in my wcf service (webHttpBinding binding in domain network) but i have an authentication error:
WCF - The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Basic realm="mySoapServiceName"
It is IIS User problem ?
Thanks

SAP is using basic auth. You need to specify the username and password after you have created the proxy, for example:
proxy.Credentials.UserName.UserName = "joe";
proxy.Credentials.UserName.Password = "doe";

BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
EndpointAddress ea = new EndpointAddress("url de mon web service soap");
SfcServices.SFCProcessingInClient myClient = new SfcServices.SFCProcessingInClient(myBinding, ea);
myClient.ClientCredentials.UserName.UserName = _MESwsLogin;
myClient.ClientCredentials.UserName.Password = _MESwsPassword;
SfcServices.SFCStateRequestMessage_sync srm = new SfcServices.SFCStateRequestMessage_sync();
SfcServices.SFCStateRequest sr = new SfcServices.SFCStateRequest();
srm.SfcStateRequest = sr;
sr.SiteRef = new SfcServices.SiteRef();
sr.SiteRef.Site = _MESsite;
sr.SfcRef = new SfcServices.SFCRef();
sr.SfcRef.Sfc = "12345678903";
sr.includeSFCStepList = true;
SfcServices.SFCStateConfirmationMessage_sync response = myClient.FindStateByBasicData(srm);
strOrdreFab = response.SfcStateResponse.SFCStatus.Sfc.ShopOrderRef.ShopOrder;
strCodeProduit = response.SfcStateResponse.SFCStatus.Sfc.ItemRef.Item;
strIndice = response.SfcStateResponse.SFCStatus.Sfc.ItemRef.Revision;

Related

Secured selfhosted WCF service: load certificate from file

I have a selfhosted WCF service publishing a REST web API. The service is configured programmatically, and currently is correctly working via HTTP.
Now I need to make it work over HTTPS, with an authentication based on certificate file.
I know the suggested way to do this is installing the certificate in the Windows Certificate Store on the server machine, but this way is not possible in my circumstances.
I need to load the certificate from the file.
After some resarches, I wrote my code, but when I try accessing the web service, a System.ServiceModel.CommunicationException is thrown, with the message:
An error occurred while making the HTTP request to ... This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server.
Here's my code for the server side:
_host = new WebServiceHost(_hostedService, Uri);
//Configuring the webHttpBinding settings
var httpBinding = new WebHttpBinding();
httpBinding.Security.Mode = WebHttpSecurityMode.Transport;
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
httpBinding.SendTimeout = new TimeSpan(0, 5, 0);
httpBinding.MaxBufferSize = 2147483647;
httpBinding.MaxBufferPoolSize = 2147483647;
httpBinding.MaxReceivedMessageSize = 2147483647;
httpBinding.ReaderQuotas.MaxDepth = 2147483647;
httpBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
httpBinding.ReaderQuotas.MaxArrayLength = 2147483647;
httpBinding.ReaderQuotas.MaxBytesPerRead = 2147483647;
httpBinding.ReaderQuotas.MaxNameTableCharCount = 2147483647;
//Add the endpoint with the webHttpBinding settings to the WebServiceHost configuration
_host.AddServiceEndpoint(typeof(IService), httpBinding, Uri);
ServiceDebugBehavior stp = _host.Description.Behaviors.Find<ServiceDebugBehavior>();
stp.HttpHelpPageEnabled = false;
ServiceBehaviorAttribute sba = _host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
sba.InstanceContextMode = InstanceContextMode.Single;
ServiceMetadataBehavior smb = new ServiceMetadataBehavior() { HttpsGetEnabled = true };
_host.Description.Behaviors.Add(smb);
X509Certificate2 trustedCertificate = new X509Certificate2("certificate.pfx", "password");
_host.Credentials.ServiceCertificate.Certificate = trustedCertificate;
_host.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
Here's my code for the client side:
var httpBinding = new WebHttpBinding();
httpBinding.Security.Mode = WebHttpSecurityMode.Transport;
httpBinding.Security.Transport = new HttpTransportSecurity() { ClientCredentialType = HttpClientCredentialType.Certificate };
var httpUri = new Uri(String.Format("https://{0}:{1}", ipAddress, tcpPort));
var httpEndpoint = new EndpointAddress(httpUri);
var newFactory = new ChannelFactory<IService>(httpBinding, httpEndpoint);
newFactory.Endpoint.Behaviors.Add(new WebHttpBehavior());
X509Certificate2 trustedCertificate = new X509Certificate2("certificate.pfx", "password"); //SSL
newFactory.Credentials.ClientCertificate.Certificate = trustedCertificate;
var channel = newFactory.CreateChannel();
var response = channel.Ping("helo");
The Exception is thrown on the last line (channel.Ping("helo")).
I need to make it work WITHOUT installing the certificate on the server machine.
Thank you very much.
Bye.
As far as I know, when we host the self-hosted WCF service over Https, whatever way we use (load certificate file or configure the certificate via Windows Certificate Store), it is impossible to make the service works normally. The only way we need to do is binding the certificate manually by using the following command.
netsh http add sslcert ipport=0.0.0.0:8000 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}
Here is official document, wish it is useful to you.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate
https://learn.microsoft.com/en-us/windows/desktop/http/add-sslcert
Here are some examples were ever written by me.
WCF Service over HTTPS without IIS, with SSL Certificate from CERT and KEY strings or files
Chrome (v71) ERR_CONNECTION_RESET on Self Signed localhost on Windows 8 Embedded
Feel free to let know if there is anything I can help with.

How do I send basic authentication credentials for a prem wcf https service over azure relay C#?

I have a WebAapp on Azure that sends a request to Azure Relay. It should transfer to a listener on premises WCF HTTPS service hosted on IIS that requires basic authentication. How do I send authorization basic header for the onprem WCF service over the Azure Relay . How do I send ? example,
"Authorization": "Basic 239837987XYC"
I have used channel factory,
var ChannelFactory<Overview.MyChannel> cf;
var relayNamespace ="myrelaynamespace";
var relayListener = "myrelaylistener";
var endPointAddress = new EndpointAddress(ServiceBusEnvironment.CreateServiceUri("https", relayNamespace, relayListener));
cf = new ChannelFactory<Overview.ItServiceManagementAOChannel>(binding, endPointAddress);
ClientCredentials loginCredentials = new ClientCredentials();
loginCredentials.UserName.UserName = "onpremWCFusername";
loginCredentials.UserName.Password = "onpremWCFpassword";
cf.Endpoint.Behaviors.Add(new TransportClientEndpointBehavior
{
TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(ConfigurationManager.AppSettings.Get("WcfRelayKeyName"), ConfigurationManager.AppSettings.Get("WcfRelayKey"))
});
cf.Endpoint.Behaviors.Add(loginCredentials);
I get the Error: The value could not be added to the collection, as the collection already contains an item of the same type: 'System.ServiceModel.Description.ClientCredentials'. This collection only supports one instance of each type.
Parameter name: item
using (var ch = cf.CreateChannel())
{
try
{
var resp = ch.CreateTaskAsync(req).Result;
}
}
Try to specify the windows credential as client credential.
factory.Credentials.Windows.ClientCredential.UserName = "administrator";
factory.Credentials.Windows.ClientCredential.Password = "123456";
IService sv = factory.CreateChannel();
Feel free to let me know if the problem still exists.

WCF basicHttpBinding and HTTP proxy

I'm trying to get my generated WCF ServiceClient to send its requests to the WCF service through a HTTP (not HTTPS) proxy with username/password authentication, however I just can't get it work. My WCF service uses basicHttpBinding so I tried to configure my ServiceClient instance like so:
var svc = new ServiceClient();
var b = svc.Endpoint.Binding as BasicHttpBinding;
b.ProxyAddress = new Uri(proxyAddress);
b.UseDefaultWebProxy = false;
b.Security.Mode = BasicHttpSecurityMode.Transport;
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
b.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Basic;
svc.ClientCredentials.UserName.UserName = proxyUsername;
svc.ClientCredentials.UserName.Password = proxyPassword;
This however results in a System.ArgumentException saying:
The provided URI scheme http is invalid. expected https
When I set the b.Security.Mode to BasicHttpSecurityMode.None though, it seems the HTTP proxy settings are ignored by WCF altogether!
The second solution I tried was to set the DefaultWebProxy property of WebRequest and set the UseDefaultWebProxy property to true such as so:
var webProxy = new WebProxy(proxyAddress, true);
webProxy.Credentials = new NetworkCredential(proxyUsername, proxyPassword);
WebRequest.DefaultWebProxy = webProxy;
var svc = new ServiceClient();
var b = svc.Endpoint.Binding as BasicHttpBinding;
b.UseDefaultWebProxy = true;
However this also doesn't work and ServiceClient doesn't send it's requests through the HTTP proxy.
I'm out of ideas here so please let me know what I am doing wrong, thank you!
Set the security mode to BasicHttpSecurityMode.TransportCredentialOnly. This allows for passing plain-text authentication details over HTTP.

Does Mono\Xamarin support Basic auth?

I'm trying to run this code with Xamarin.Android but it falls down on last line(System.Net.WebException: There was an error on processing web request: Status code 401(Unauthorized)):
var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
var endPointUri = new Uri(#"http://192.168.1.241/edo/Euphrates.svc/ILogonService-Basic");
var factory = new ChannelFactory<ILogonService>(binding, new EndpointAddress(endPointUri));
factory.Credentials.UserName.UserName = "test";
factory.Credentials.UserName.Password = "test";
ILogonService service = factory.CreateChannel();
Console.WriteLine(service.Logon("test"));
On windows console app everything works very well.
You can use basic authentication in an url in Xamarin:
https://username:password#www.example.com/webcallback?foo=bar

Using BasicHttpSecurityMode.TransportWithMessageCredential in a partial (medium) trust enviroment

I have an application which consumes a WCF web service, i log in to said service using credentials supplied by the company who maintain the service.
This is the code I created for binding the service.
I used svcutil.exe to generate a ClientSearchService.cs file and imported it into the project
BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Name = "BasicHttpBinding_IClientSearch";
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
myBinding.MaxBufferSize = 524288;
myBinding.MaxBufferPoolSize = 524288;
myBinding.MaxReceivedMessageSize = 524288;
myBinding.ReaderQuotas.MaxDepth = 32;
myBinding.ReaderQuotas.MaxArrayLength = 524288;
myBinding.ReaderQuotas.MaxStringContentLength = 524288;
myBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
EndpointAddress endPointAddress = new EndpointAddress(serviceEndPointAddress);
ClientSearchClient myClient = new ClientSearchClient(myBinding, endPointAddress);
myClient.ClientCredentials.UserName.UserName = userName;
myClient.ClientCredentials.UserName.Password = userPass;
var request = new schemas.advancedcheck.co.uk.DriverChecksRequest();
request.FromDate = new DateTime(2014, 1, 1);
request.ToDate = DateTime.Now;
var response = myClient.GetDriverChecks(request);
If i execute this in a full trust environment i have no issues and the data I expect to see is returned successfully, however, where the code will be hosted will be a partial trust enviroment and when ran in a partial trust enviroment it throws this error:
The Binding with name BasicHttpBinding_IClientSearch failed validation because it contains a BindingElement with type System.ServiceModel.Channels.TransportSecurityBindingElement which is not supported in partial trust. Consider using BasicHttpBinding or WSHttpBinding, or hosting your application in a full-trust environment.
is there another method i can use to consume this web service in a partial trust enviroment?

Categories

Resources