WCF SSL .pfx Binding - c#

My API call another secure API internally below is my code :
string ID = Convert.ToString(ConfigurationManager.AppSettings["ID"]);
string Password = Convert.ToString(ConfigurationManager.AppSettings["Password"]);
string client_ID = Convert.ToString(ConfigurationManager.AppSettings["client_ID"]);
string client_secret = Convert.ToString(ConfigurationManager.AppSettings["client_secret"]);
string patchURI = Convert.ToString(ConfigurationManager.AppSettings["SecureApi"]);
patchURI = patchURI + "?client_ID=" + client_ID + "&client_secret=" + client_secret;
string JsonStringParams = jsonStringRequest();
//ServicePointManager.Expect100Continue = true;
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
byte[] data = Encoding.UTF8.GetBytes(JsonStringParams);
var request = (HttpWebRequest)WebRequest.Create(patchURI);
request.KeepAlive = false;
request.Method = "POST";
request.ContentType = "application/json";
request.ContentType = "application/x-www-form-urlencoded";
request.Headers.Add("UserName", LDAPID);
request.Headers.Add("Password", Password);
string requestData = JsonStringParams;
data = Encoding.UTF8.GetBytes(requestData);
Stream dataStream = request.GetRequestStream();
dataStream.Write(data, 0, data.Length);
dataStream.Close();
var response = request.GetResponse(); // failed at this stage Error : The request was aborted: Could not create SSL/TLS secure channel.",
string result = new StreamReader(response.GetResponseStream()).ReadToEnd();
result = new StreamReader(response.GetResponseStream()).ReadToEnd();
my patchURI contains a https link which needs a .pfx SSL and client has already same .cer/crt installed
When i use the patchURI and pass SSL in SOAPUI Tool i get response from Client server, but when i use through this code it fails and generates and err : - Failed to Create SSL Channel.

The error typically indicates that the trust relationship has not been established yet. In order to establish the relationship between the client-side and the server-side, we should install each other’s certificate in the TRUSTED ROOT CERTIFICATION AUTHORITIES store.
It is not recommended to call the WCF service by using an Http client library except that the WCF service created by WebHttpbinding(Restful WCF service). We usually call the WCF soap web service by using a client proxy. The below code can be used for manually verifying the certificate while sending an Http request.
ServicePointManager.ServerCertificateValidationCallback += delegate
{
return true;
};
Besides, please post the complete error message if the error still exists.
Feel free to let me know if there is anything I can help with.

Related

How to encrypt username/password for session

I am making a call to a 3rd party service via https (using HttpWebRequest and sending a username, password in order to return a token which is then needed to make future requests for data). The service would only be required to list items on a public ASPNet website.
There will be no database involved so session or cookies would be storing the token.
To get the token I send a POST request which includes the username/password but I can see these details (username/password) in Fiddler (headers text tab I think but can confirm if anyone asks) - personally I thought I shouldn't? When I make a GET request to get the items I send the token and all works.
So am I supposed to encrypt the username/password somehow before making retrieving the token? If yes how would I do that?
I just feel that anyone could check the POST request and see what's going on. I could be wrong but happy to test any theories.
Edit 1
Here is the code i am sending the POST request. Please note the username and password along with the URL which is https
private string UsernamePassword()
{
string un = new JavaScriptSerializer().Serialize(new
{
User = "abc",
Password = "123"
});
return un;
}
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create("https://site.data.com");
wr.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate, br");
wr.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-GB,en-US;q=0.9,en;q=0.8");
wr.Headers.Add("Sec-Fetch-Site", "same-origin");
wr.Headers.Add("Sec-Fetch-Mode", "cors");
wr.Accept = "application/json";
wr.ContentType = "application/json";
byte[] data = null;
wr.Method = "POST";
data = Encoding.UTF8.GetBytes(UsernamePassword());
wr.ContentLength = data.Length;
wr.KeepAlive = true;
wr.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
try
{
using (Stream stream = wr.GetRequestStream())
{
stream.Write(data, 0, data.Length);
stream.Flush();
stream.Close();
}
using (HttpWebResponse httpResponse = (HttpWebResponse)wr.GetResponse())
{
var encoding = Encoding.GetEncoding(httpResponse.CharacterSet);
#germi is right. That's exactly what TLS/Https is for. The fact that you can see the content of your https request doesn't mean anyone can.
As long as your endpoint is using https (and not http), the exchange will happen over an encrypted channel. If you want to verify, install Wireshark and see for yourself.

I am trying to consume data from the Avaya office manager API. CertificateValidationCallback causing error

My error is
The request was aborted: Could not create SSL/TLS secure channel.
I am using the example code from the Avaya office management api documentation.
I can't get CertificateValidationCallback to compile.
protected void Page_Load(object sender, EventArgs e)
{
ServicePointManager.ServerCertificateValidationCallback = new
System.Net.Security.RemoteCertificateValidationCallback(CertificateValidationCallback);
String username = "";
String password = "";
String url = "https://10.207.251.41:7070/WebManagement/ws/sdk/security/authenticate";
CookieContainer cookieContainer = new CookieContainer();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Credentials = CredentialCache.DefaultCredentials;
request.Method = "GET";
request.ContentType = "application/json";
request.Headers.Add("X-User-Client", "Avaya-WebAdmin");
request.Headers.Add("X-User-Agent", "Avaya-SDKUser");
String credentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(username + ":" + password));
request.Headers.Add("Authorization", "Basic " + credentials);
request.CookieContainer = cookieContainer;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var resStream = response.GetResponseStream();
var reader = new StreamReader(resStream);
String responseContent = reader.ReadToEnd();
response.Close();
}
If the certificate is not trusted by Certification Authority (and I don't think so because of the request, but it sounds instead like a test certificate), you shall install it on your system as trusted by MMC console, adding "certificate" snap/in, selecting your local pc as destination. Then, in the snap in shall appear a list of certificate folders, find the "trusted root certificates" and import the certificate (if you don't have it, I think that you can download it with the browser visiting the link https://10.207.255.45:7070 ). Once it's installed there, this could fix your problem

How to invoke a Web Service which requires a certificate in C#?

I need to communicate with a third party which has a .asmx web service. This web service is using https. I have the required certificate (.pfx).
When first trying to add this service using Add Service Reference in Visual Studio, I got an error. I got passed this error by importing the certificate into the Personal store. After I did that, I tried to add the Service Reference again and it works. So now I can create an instance of the web service. Nice.
But now I want to invoke the service. And when I do that I get this error:
302 Notification: Digital Certificate Missing
So how can I tell my service to use the right certificate?
I finally managed to fix my problem as follows:
var service = new Service1SoapClient();
service.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.TrustedPublisher, X509FindType.FindByIssuerName, "name_of_issuer");
((BasicHttpBinding)service.Endpoint.Binding).Security.Mode = BasicHttpSecurityMode.Transport;
((BasicHttpBinding)service.Endpoint.Binding).Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
Please use Certificate.pfx and install it with password.
Try adding this before getting the request stream:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
request.ProtocolVersion = HttpVersion.Version10;
request.ClientCertificates.Add(new X509Certificate2("YourPfxFile(full path).pfx", "password for your pfx file");
Depending on your security requirements and environment, you may need to use a different SecurityProrocolType value.
I was also facing "The request was aborted: Could not create SSL/TLS secure channel" while requesting a web service.
Fixed issue with below code, hope this will help someone and save time.
HttpWebRequest web_request = (HttpWebRequest)WebRequest.Create("https://yourservices/test.asmx");
web_request.ContentType = "text/xml;charset=\"utf-8\"";
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
web_request.ProtocolVersion = HttpVersion.Version10;
X509Certificate2Collection certificates = new X509Certificate2Collection();
certificates.Import(certName, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
web_request.ClientCertificates = certificates;
web_request.Accept = "text/xml";
web_request.Method = "POST";
using (Stream stm = web_request.GetRequestStream())
{
using (StreamWriter stmw = new StreamWriter(stm))
{
stmw.Write(soap);
}
}
WebResponse web_response = null;
StreamReader reader = null;
try
{
web_response = web_request.GetResponse();
Stream responseStream = web_response.GetResponseStream();
XmlDocument xml = new XmlDocument();
reader = new StreamReader(responseStream);
xml.LoadXml(reader.ReadToEnd());
}
catch (Exception webExp) {
string exMessage = webExp.Message;
}

ASP.NET C# page with SSL and Mutual Auth from smartcard

I would like create a login page for user with smartcard authentication and redirect to third party service. I have verified in java and it's work (but dont'know how).
My Https Page have to read certificate with Request.ClientCertificate
after i need to create a webrequest (a Soap Envelope) to 3th party services.
When i execute this code on IIS Express locally , all works (private key of certificate is present)
when i publish on remote IIS this code don't work , the message i receive is
"Authorization Required" (private key of certificate is not present)
This the code is use:
public HttpWebRequest CreateWebRequest(string url)
{
Uri uri = new Uri(url);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
System.Net.ServicePointManager.ServerCertificateValidationCallback += mIgnoreBadCertificates;
webRequest.Proxy = null;
webRequest.Headers.Add("SOAP:Action");
webRequest.KeepAlive = true;
webRequest.ProtocolVersion = HttpVersion.Version10;
webRequest.Headers.Add("X-WASP-User", DataOnCertifcate);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
webRequest.AuthenticationLevel = AuthenticationLevel.MutualAuthRequired;
if (Request.ClientCertificate != null)
{
webRequest.ClientCertificates.Clear();
webRequest.ClientCertificates.Add(Request.ClientCertificate);
}
return webRequest;
}
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);
HttpWebRequest request = CreateWebRequest(Url);
using (Stream stream = request.GetRequestStream())
{
envelope.Save(stream);
}
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
IAsyncResult asyncResult = request.BeginGetResponse(null, null);
asyncResult.AsyncWaitHandle.WaitOne();
string soapResult = "";
using (WebResponse webResponse = request.EndGetResponse(asyncResult))
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
}
1) on IIS there is SSL enabled
2) When i access to my https page , browser show me a list of certificate.
3) I choice the certificate present into smartcard, and i insert the Pin corretly
4) my https test page , show me the correct certificate and public key information, but no private key information (on remote Server, meanwhile on local server all works)
5) i Get this error
401 Authorization Required Authorization Required This server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required. Apache/2.2.3 (Red Hat) Server at server name Port 443
How can i fix this problem?

Accessing ssl server (web service) from .net client

I’m tryng to access a ssl server (web service) from a .net client (c#). I have access to a java client code that can connect to the server. Included in the source code are 3 files (saPubKey.jks, WebServices.pfx and trustStore) and I think that only 2 of the 3 are used in the java example.
private void setSSLConnection(WSBindingProvider bp){
KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(this.getClass().getClassLoader().getResourceAsStream("WebServices.pfx"), "password".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "password".toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
KeyStore ts = KeyStore.getInstance("JKS");
ts.load(this.getClass().getClassLoader().getResourceAsStream("trustStore"), "pass".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
bp.getRequestContext().put(JAXWSProperties.SSL_SOCKET_FACTORY, sslContext.getSocketFactory());
}
The code I have for the c# client is this
var clientCertificate = new X509Certificate2(#"C:\WebServices.pfx", "password");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://blablabla.org:700/fws/ftrs");
req.ClientCertificates.Add(clientCertificate);
req.Headers.Add("SOAPAction", "\"https://blablabla.org:700/fws/ftrs/Rgdvice\"");
req.ContentType = "text/xml;charset=\"utf-8\"";
req.Accept = "text/xml";
req.Method = "POST";
using (Stream stm = req.GetRequestStream())
{
using (StreamWriter stmw = new StreamWriter(stm))
{
stmw.Write(soap);
}
}
WebResponse response = req.GetResponse(); //(500) Internal Server Error.
Stream responseStream = response.GetResponseStream();
Method req.GetResponse() throws "(500) Internal Server Error."
With no client certificates added I get: "An unexpected error occurred on a send."
I also tried this line of code with no luck:
ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);
I'm new to ssl and certificates, and really need help accessing the ssl server from c#.
This could be unrelated but make sure web service is not in the app_code folder.

Categories

Resources