Consuming J2EE web service signing request but receiving unsigned response - c#

I'm consuming a third party J2EE web service that requires sign the request with a certificate, but the web service is responding an unsigned response.
This is the way I'm doing the request:
public static WcfServiceNamespace.ResponseType GetResponse(X509Certificate2 certificate)
{
var request = GetExampleRequest();
var endPoint = new EndpointAddress($"https://endPoint.url/contoso");
var binding = GetCustomBinding();
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
using (var client = new WcfServiceNamespace.ServicePortTypeClient(binding, endPoint))
{
client.Endpoint.Contract.ProtectionLevel = ProtectionLevel.Sign;
client.ClientCredentials.ClientCertificate.Certificate = certificate;
return client.ProcessRequest(request);
}
}
private static Binding GetCustomBinding()
{
var c = new CustomBinding();
var version = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
var sec = SecurityBindingElement.CreateCertificateOverTransportBindingElement(version);
sec.EnableUnsecuredResponse = true;
sec.AllowInsecureTransport = true;
sec.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
c.Elements.Add(sec);
c.Elements.Add(new TextMessageEncodingBindingElement() {MessageVersion = MessageVersion.Soap11});
c.Elements.Add(new HttpsTransportBindingElement() { RequireClientCertificate = true });
return c;
}
The java web service is responding correctly the request without any header:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<!-- correct response -->
</soapenv:Body>
</soapenv:Envelope>
But WCF client is throwing an exception when it tries to process the response:
System.ServiceModel.Security.MessageSecurityException: 'Cannot find a token authenticator for the 'System.IdentityModel.Tokens.X509SecurityToken' token type. Tokens of that type cannot be accepted according to current security settings.'
I already tried this configuration:
WCF - Cannot find a token authenticator for X509SecurityToken
But it does not resolve my problem because the header of the response is totally empty as I explained before and the endpoint is using https but has no certificate to trust.
My question is:
Is there any way to configure WCF to correctly sign the request but ignore the response security?
Edit:
I already tried this questions:
IBM DataPower 3.7.1.x issues with WCF clients
WCF error calling WS-Security web service: Cannot find a token authenticator for the X509SecurityToken
But the answers don't help
Edit:
I make it work with WSE3 but I want use a newer technology. If it works in WSE3, Why not in WCF?

Can we use the below tools to generate the SOAP client, with which we can call the service like the below method?
https://learn.microsoft.com/en-us/dotnet/framework/wcf/servicemodel-metadata-utility-tool-svcutil-exe
It is a built-in tool in Visual Studio, and we can generate the client proxy class and the compatible custom binding and security mode configuration by using the SVCUtil command. the client proxy will automatically use the configuration compatible with the server to create the request when instantiating.
Alternatively, we could generate the client proxy by means of the Add service reference menu.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
I have never called the J2EE web service, please let me know if it helps.

Related

C#.Net Core 3.1 HttpRequest timeout or SSL connection issue

Ok i have the following code
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
clientHandler.UseProxy = false;
using (HttpClient client = new HttpClient(clientHandler))
{
var reqUri = string.Format("{0}/{1}?getBIC=true&validateBankCode=true", AppSettings.Instance.ValidationSettings.IBANValidationUri, iban);
Logger.Instance.LogInfo("IBAN Validation: Sending request");
using (HttpResponseMessage res = await client.GetAsync(reqUri))
{
using (HttpContent content = res.Content)
{
if (content != null)
{
Logger.Instance.LogInfo("IBAN Validation: Reading data");
var data = res.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(data.Result))
{
result = JsonConvert.DeserializeObject<IBANValidationResult>(data.Result);
}
}
}
}
}
Now this code simply makes a rquest to the openiban api to get the specific bank information from a IBAN number.
This code runs on a ASP.NET Core 3.1 Web API that is running on a IIS Server.
Now we have 3 exact same server with the same web api.
The problem:
when i call the service from a browser on server 1, the service works fine i get the response etc.
when i call the service from a browser on server 2 it works also fine.
when i call the service from a browser on server 3 it takes too long and then i receive following error on the backend:
ERROR: The SSL connection could not be established, see inner
exception
ERROR: Authentication failed because the remote party has closed the
transport stream.
The funny thing is: This issue does not depend on one server, sometimes the server 3 works but then server 2 does not work, sometimes server 1 does not work an the other servers are working.
Does anybody have a clue what is going on here?
PS: The SSL certificates are installed on the server
Thanks a lot

How to detect SSL Policy errors with .net?

I'm totally new to handling policy errors when making web requests so I'm a little bit confused at this point..
I have this task to call a web service but not allow the call to be made if the server I'm calling has an invalid certificate.
So I created a method to call a site with invalid cerificate and using ServerCertificateValidationCallback to prevent the call to be made if the certificate is invalid.
What I need is a quick walkthrough in how to detect the invalid certificate inside my handler. I would have thought that the call to "revoked.badssl.com" would have caused something in the sslPolicyErrors object to be something other than "none" but is this not the case? I see no difference at this point in calling badssl or my other url that has a valid certificate.
For example: if https://pinning-test.badssl.com/ is opened in chrome it shows a "ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN" (although IE shows the page). How do I find this information that chrome deems as an invalid certificate so I can, if I want to, also handle it as invalid in my code??
This is my code I'm trying with at the moment:
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) =>
{
if(someError?!)
return false;
return true;
};
using (HttpClient client = DefaultHttpClient())
{
Uri uri = new Uri("https://revoked.badssl.com/");
string jsonObj = "{}";
var content = new StringContent(jsonObj, Encoding.UTF8, "application/json");
HttpResponseMessage response = client.PostAsync(uri, content).Result;
}
By default the revocation check is not performed. You need to set it on the ServicePointManger Class for your application to check it.
System.Net.ServicePointManager.CheckCertificateRevocationList = true;

Make HTTPS request using HttpClient in Xamarin.iOS

I'm trying to get the data from a WCF serving json data from a https url.
Using this code it works great pointing at a HTTP url (note not HTTPS).
HttpContent content = new StringContent("{ var1: test }", Encoding.UTF8, "application/json");
var client = new System.Net.Http.HttpClient();
client.Timeout = new TimeSpan(0, 0, 60);
var response = client.PostAsync(url, content);
var jsonResponse = response.Result.Content.ReadAsStringAsync().Result;
double kiloBytesData = (jsonResponse.Length * sizeof(Char)) / 1024d;
But for HTTPS I get:
System.Net.WebException: Error: SecureChannelFailure (Unable to read
data from the transport connection: Connection reset by peer.)
Also note that I can browse to the https url and get the right response so I'm quite certain the WCF/IIS server is behaving as it should.
According to this thread: https://forums.xamarin.com/discussion/69778/restsharp-is-not-working-after-updating-xamarin-studio-to-6-0-1-version
It can be fixed by changing the TLS setting under project properties to Mono instead of Apple. I did that and it made no change.
Yet another site (lost the url now) suggested that it might work (although isen't a good solution) to add this to the AppDelegate.cs FinishedLaunching method to allow all certificates:
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) =>
{
if (cert != null) System.Diagnostics.Debug.WriteLine(cert);
return true;
};
This does not work either and causes the same error.
If it makes any difference, the SSL certificate is from here https://letsencrypt.org/ (awesome service btw).
Any more suggestions as to how one can post and receive json data from an HTTPS bound WCF in Xamarin.iOS?

User authentication when consuming a REST webservice with ServiceStack

The ServiceStack docs are full of examples on how to use server side implementation of authentication of a user. But how does one set the user credentials on the client side?
I use ServiceStack to consume a JSON REST service like this:
var restClient = new JsonServiceClient (baseUri);
var response = restClient.Get<MyResponse> ("/some/service");
How can I add any form of authentication to the request? The webservice I want to consume uses OAuth 1.0, but I am interested in adding custom authentication, too.
In my code, I have previously performed OAuth token exchange successfully, so I already own a valid access token and need to sign every REST request now using this access token and its token_secret.
ServiceStack's AuthTests shows different ways of authenticating when using the ServiceStack Service Clients. By default BasicAuth and DigestAuth is built into the clients, e.g:
var client = new JsonServiceClient(baseUri) {
UserName = UserName,
Password = Password,
};
var request = new Secured { Name = "test" };
var response = client.Send<SecureResponse>(request);
Behind the scenes ServiceStack will attempt to send the request normally but when the request is rejected and challenged by the Server the clients will automatically retry the same request but this time with the Basic/Digest Auth headers.
To skip the extra hop when you know you're accessing a secure service, you can tell the clients to always send the BasicAuth header with:
client.AlwaysSendBasicAuthHeader = true;
The alternative way to Authenticate is to make an explicit call to the Auth service (this requires CredentialsAuthProvider enabled) e.g:
var authResponse = client.Send<AuthResponse>(new Auth {
provider = CredentialsAuthProvider.Name,
UserName = "user",
Password = "p#55word",
RememberMe = true, //important tell client to retain permanent cookies
});
var request = new Secured { Name = "test" };
var response = client.Send<SecureResponse>(request);
After a successful call to the Auth service the client is Authenticated and if RememberMe is set, the client will retain the Session Cookies added by the Server on subsequent requests which is what enables future requests from that client to be authenticated.
Answering myself, as I've found a nice way to do it using the LocalHttpWebRequestFilter hook in the JsonServiceClient:
For securing a web service with OAuth 1.0a, every http request has to send a special Authorization: header. Within this header field, a hash (signature) must be send that uses some characteristics of the request as input data, like the hostname, request url and others.
Now it seems the LocalHttpWebRequestFilter is called by ServiceStack right before the http request is made, and exposes the underlying HttpWebRequest object, where one can add extra headers and access the required fields of the request.
So my solution is now basically:
var client = new JsonServiceClient (baseUri);
client.LocalHttpWebRequestFilter += (request) => {
// compute signature using request and a previously obtained
// access token
string authorization_header = CalculateSignature (request, access_token);
request.Headers.Add ("Authorization", authorization_header);
};
var response = client.Get<MySecuredResponse> ("/my/service");
Note that I use the Devdefined.OAuth library to do all the heavy stuff in CalculateSignature(). The creation of request token, obtaining user authorization, and exchanging the request token for access token as required by OAuth is done outside of ServiceStack, before the above service calls.

Sending an API CAll with PayPal SOAP API

Ok, so I have the service reference in my .NET project. And yes I know that you now have access to proxy classes.
But in the past, I am used to doing this via an HttpWebRequest object using NVP, but never tried using the WSDL and sending a SOAP request this way.
I'm not quite sure which object to use to send the request. Not sure where to start here. I've looked at the docs but seen no good examples out there for .NET and PayPal.
Other than a WSDL vs. sending an HttpWebRequest via a NVP API and querystring params, I really do not understand if there's a difference in how you send the request. It's all just over Http so can't you use HttpWebRequest also over a SOAP API (using WSDL)?
You start by generating a service reference from the metadata: Right click on the project -> Add Service Reference and point to the WSDL url: https://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl
This will generate proxy classes to the current project which could be used to send requests:
using (var client = new PayPalAPIInterfaceClient())
{
var credentials = new CustomSecurityHeaderType
{
Credentials = new UserIdPasswordType
{
Username = "username",
Password = "password"
}
};
var request = new AddressVerifyReq
{
AddressVerifyRequest = new AddressVerifyRequestType
{
Street = "some street",
Zip = "12345"
}
};
var response = client.AddressVerify(ref credentials, request);
}

Categories