C#: How to accept an invalid SSL certificate programmatically
In the project I’m working on at the moment, we have a requirement to call some REST services using .NET#’s built-in System.Net.HttpWebRequest class. The calls will eventually be over SSL using a properly issued certificate when we go live, but for testing we’ve been using a self-signed certificate.
When you navigate to an HTTP URL with a dodgy certificate in a browser, you get a warning that gives you the option to ignore the problems. In code, this just results in an exception being thrown. The exception is a System.Security.Authentication.AuthenticationException (wrapped in a System.Net.WebException), with an error message of “The remote certificate is invalid according to the validation procedure.”
So, for testing, we needed to find a way to bypass the certificate validation. It turns out that you need to provide a RemoteCertificateValidationCallback delegate and attach it to ServicePointManager.ServerCertificateValidationCallback. What’s not clear is what happens if two threads are competing to set this property to different values, since it’s a static property. Reflector suggests that the property set method doesn’t do anything fancy, so you could easily get into a race condition.
Anyway, here’s s snippet that shows how to do this. Hopefully someone will find it useful, because it took me a while to find.
// callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors policyErrors
)
{
if (Convert.ToBoolean(ConfigurationManager.AppSettings["IgnoreSslErrors"]))
{
// allow any old dodgy certificate...
return true;
}
else
{
return policyErrors == SslPolicyErrors.None;
}
}
private static string MakeRequest(string uri, string method, WebProxy proxy)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
webRequest.AllowAutoRedirect = true;
webRequest.Method = method;
// allows for validation of SSL conversations
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(
ValidateRemoteCertificate
);
if (proxy != null)
{
webRequest.Proxy = proxy;
}
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)webRequest.GetResponse();
using (Stream s = response.GetResponseStream())
{
using (StreamReader sr = new StreamReader(s))
{
return sr.ReadToEnd();
}
}
}
finally
{
if (response != null)
response.Close();
}
}
Comments
27 Responses to “C#: How to accept an invalid SSL certificate programmatically”
Leave a Reply

Hi, Very thanks for the code.
I am using this code to validate SSL certificate of the web site on which I need to post vital data.
I want to know, if I found that SSL certificate got expired or anything wrong with the certificate then how can I stop the request. Please do respond. Thanks
hi,
its nice to read this article.
i want to do same validation for one url. can u please tell me what i have to do for the same.in method and proxy what argument i have to pass as i m new in this SSL side i dont have any idea.
can you please help me.
thanks
James,
Thank you. You saved me a lot of R&D work.
Best,
Mark
This is great snippet. Thank you very much!
Thanks a bunch..nice help!!
You are legend!!!! saved my ass
i also had another problem that was solved by specifying the security protocol as found at:
http://blogs.msdn.com/mariya/archive/2006/06/19/637162.aspx
p.s this works for web requests/responses as well
Saved my ass, too, especially that I had 15 minutes to solve it
Any one has vb version? i cant convert the following:
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(
ValidateRemoteCertificate
);
any help will be appreciated! Thanks
It’ll be something like:
Thanks for the reply. Now the problem i face is how do i use them? I pasted them in my MasterPage which will through the certificate. Should i call the MakeRequest in my page_load? Any hints please?
I’m confused. Are you trying to download some resource from the web in your Master Page? That sounds like a very bad idea to me. You’ll definitely want to spin off a separate thread to do that I would have thought. Without understanding about what you’re trying to achieve and what your specific problem is I’m probably not going to be able to help.
If you’re trying to force your own certificate to be accepted by the user’s browser when the certificate is invalid, this approach isn’t going to work. Clearly that would be a great way to con old ladies out of money and is the precise reason that SSL exists in the first place: it’s up to the browser to verify the certificate with a trusted third party, not up to you to say “I know this looks invalid, but trust me it isn’t”.
Ok. Yes i was thinking to force the client browser to accept the certificate but this wasn’t in the production server. I was using that for my staging server, therefore i was hoping that all the developers doesn’t need to accept the invalid certificate everytime they are doing testing. Thanks for the advice.
It’s easy enough to achieve. You just need to add an exclusion for the certificate in your browser. How you do that varies depending on the browser you’re using.
You rule!
Though i have a valid certificate , i am getting the below exception. Please help
System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel
I have pasted the code below
X509Certificate2 x509 = new X509Certificate2();
X509Store store = new X509Store(StoreLocation.LocalMachine);
byte[] certRawData;
try
{
certRawData = File.ReadAllBytes(ConfigurationManager.AppSettings["CERT_PATH"].ToString());
x509.Import(certRawData);
store.Open(OpenFlags.ReadWrite);
store.Add(x509);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
//MPG Http Post
HttpWebRequest webReq;
webReq = (HttpWebRequest)WebRequest.Create(strURL);
webReq.Method = “GET”;
webReq.ClientCertificates.Add(x509);
HttpWebResponse webRes;
StreamReader srResponse;
webRes = (HttpWebResponse)webReq.GetResponse();
srResponse = new StreamReader(webRes.GetResponseStream(), Encoding.ASCII);
String strResponseText = srResponse.ReadToEnd();
srResponse.Close();
Console.WriteLine(”RESPONSE: ” + strResponseText);
//End of Http Post
store.Close();
}
catch (Exception certException)
{
Console.WriteLine(certException.ToString());
}
Yay! That’s what I needed!
Thank you very much!
Sweet! Solved my problem with talking to a dev server without a valid certificate. Thanks!
Yay! Thanks a lot! I was having problem with a web service from a company that was a PHP shop. I’ve had nothing but trouble trying to get their service set up. The latest error I got was my system rejecting their SSL cert. They said I had to get my program to ignore SSL errors…and your code did the trick!
FYI: Don’t forget the following usings:
using System.Web;
using System.Web.Security;
@zTech,
You say that you solved your problem but you don’t say how. Could you please elaborate?
@Ravi Vooda,
Did you ever get this code to work?
@Ami
Are you having trouble getting it to work? If so, what’s the problem? Let me know and I’ll see if I can help.
Thank you ,
This information solved my testing problems.
Exactly what I needed. Thanks a lot!
Thanks a lot!! That’s what I needed!
Thanks a lot
You solved my problem
Thanks a lot
You solved my problem
Just remember to unregister the callback after you’re done, otherwise your callback will be called for every registration:
finally
{
ServicePointManager.ServerCertificateValidationCallback -= ValidateRemoteCertificate;
if (response != null) response.Close();
}