C#: How to accept an invalid SSL certificate programmatically

May 1, 2008 · Posted in Tech 

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

50 Responses to “C#: How to accept an invalid SSL certificate programmatically”

  1. Pawan on June 5th, 2008 15:41

    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

  2. Darshan Thacker on August 12th, 2008 07:28

    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

  3. Mark Miller on September 26th, 2008 19:59

    James,

    Thank you. You saved me a lot of R&D work.

    Best,

    Mark

  4. Mario & Salvo on October 17th, 2008 14:25

    This is great snippet. Thank you very much!

  5. sam on November 21st, 2008 11:05

    Thanks a bunch..nice help!!

  6. Doug on January 7th, 2009 04:15

    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

  7. Codru on May 6th, 2009 11:46

    Saved my ass, too, especially that I had 15 minutes to solve it :D

  8. jetty on May 12th, 2009 08:50

    Any one has vb version? i cant convert the following:
    ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(
    ValidateRemoteCertificate
    );

    any help will be appreciated! Thanks

  9. higgis on May 12th, 2009 09:04

    It’ll be something like:

    AddHandler ServicePointManager.ServerCertificateValidationCallback, AddressOf Me.ValidateRemoteCertificate
  10. jetty on May 13th, 2009 08:49

    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?

  11. higgis on May 13th, 2009 14:49

    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”.

  12. jetty on May 14th, 2009 02:39

    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.

  13. higgis on May 14th, 2009 09:13

    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.

  14. hamish on July 29th, 2009 11:59

    You rule!

  15. Ravi Vooda on August 11th, 2009 06:33

    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());
    }

  16. Lawyno on August 27th, 2009 15:09

    Yay! That’s what I needed!

    Thank you very much!

  17. zTech on October 21st, 2009 18:11

    Sweet! Solved my problem with talking to a dev server without a valid certificate. Thanks!

  18. Chris on October 26th, 2009 13:01

    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!

  19. Chris on October 26th, 2009 13:02

    FYI: Don’t forget the following usings:

    using System.Web;
    using System.Web.Security;

  20. Ami Schreiber on October 27th, 2009 16:29

    @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?

  21. higgis on October 27th, 2009 16:33

    @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.

  22. Bülent ÇOBAN on December 14th, 2009 08:42

    Thank you ,
    This information solved my testing problems.

  23. Jónas on June 1st, 2010 04:05

    Exactly what I needed. Thanks a lot!

  24. Dietmar on June 10th, 2010 14:53

    Thanks a lot!! That’s what I needed!

  25. Rytis ?salis on June 17th, 2010 14:25

    Thanks a lot :) You solved my problem :)

  26. Rytis Usalis on June 17th, 2010 14:25

    Thanks a lot :) You solved my problem :)

  27. Secret Agent on July 7th, 2010 19:24

    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();
    }

  28. Johnny Sokhn on August 18th, 2010 15:34

    Why writing All that code to accept an invalid SSL certificate programmatically. All what you need is one line:

    ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

  29. Jayson Pryde on October 28th, 2010 21:03

    HI all,

    I have the same implementation described above. My only problem is i’m still getting an AuthenticationException “A call to SSPI failed” though i’ve already bypassed the authentication….

    Have researched for quite sometime already but haven’t resolved this yet.
    Hope you can help me

    Many thanks :)

  30. Arun on November 1st, 2010 16:33

    Very helpful. I was previously having an older version of this which is now obsolete.

    Thanks so much.

  31. Erik on January 20th, 2011 21:49

    Great, Johnny. Your one-liner did it!

  32. pushedx on April 22nd, 2011 23:37

    Thanks a lot for this post! It was just what I needed.

  33. Morten on May 23rd, 2011 10:15

    Excellent time-saver! I owe you one ;-)

  34. MDS on July 1st, 2011 20:15

    Yes,it works.Thanks a lot.
    We just made two minor changes to the above code(though it seems it was specifically required for us only):
    1)Removed the if else condition from callback function and returned true arbitrarily
    2)Called the callback before making request as well.
    that is,
    ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);
    moved to the start of MakeRequest method.

  35. Extreme developer on July 27th, 2011 18:30

    Johnny = Master .
    Thanks a lot

  36. Sudhir C on August 1st, 2011 18:30

    Thanks.. That solved my issue..

  37. Jon Upchurch on August 9th, 2011 21:21

    Exactly what I needed and saved me a big headache, thanks!

  38. Chris Mangiapane on August 23rd, 2011 01:49

    Thanks I thought this was it….

    I’m doing a 2010 Exchange Remote PowerShell runSpace.Open() request to an https exchange server. Is there a why to ignore or handle the SSL error and still Open() the runspace and contine. In other words, I don’t have a Request/Response object.

  39. Nico on August 30th, 2011 14:04

    Thanks from Spain. I owe you a beer!!

  40. Melih on September 26th, 2011 13:11

    Thank you so much.. Very precious code…. Helped me and saved my time very much

  41. Mark on September 26th, 2011 20:44

    Thanks, saved me lots of time.

  42. Rachel Pierson on September 29th, 2011 19:37

    Great snippet, just what I needed – thanks.

    Rachel.

  43. [...] C#: How to accept an invalid SSL certificate programmatically : Jumping Through Hoops. Be Sociable, Share! Posted in Development – Tagged C, ssl « He was Smokin’ Joe No Comments Yet [...]

  44. Lily on December 1st, 2011 07:07

    Hi, i also have the same problem.(The remote certificate is invalid according to the validation procedure.)
    my question is, where do i put this code, coz i am following a tutorial from ” how to get started with webmatrix”. do i put it on the _start.cshtml. or register.cshtml.

  45. Ralph Radtke on December 5th, 2011 11:17

    Many thanks,

    your code saved me a lot of time..

  46. Sarav on January 19th, 2012 17:53

    Hi, Is there a way to customize remotecertificatevalidationcallback per request. I’m using this callback for validating a server certificate, the code change works fine. But it caused other interfaces to show the alert on server certificate which was working earlier without any issues. If you have any other suggestions to resolve this will be really helpful for me.

  47. FireGarden on January 26th, 2012 20:50

    You sire are my master. I bow down to your greatness with infinite gratitude for providing this awesomeness code.

    Merci

  48. metoo on January 28th, 2012 11:17

    hello all,
    I would like to use this exepction as I ‘m trying to create an application.
    But as I’m very newbie I have lot of errors

    can anyone create juste a project example an upload it just to see how to use this code correctly

    Thank you

  49. beginer on January 29th, 2012 14:21

    use
    Dim webRes as HttpWebResponse

    webres.enablessl = false

  50. metoo on January 31st, 2012 08:53

    webres.enablessl = false
    but in this case you disable the ssl ?
    I need to post a form on a website, but there is an invalide certificate which is opeining a popup.

    if anyone can loose 3 minutes of his time :s
    Thank you
    Sami

Leave a Reply