.NET
SSL certificate
web services
error handling
debugging

Bypass invalid SSL certificate errors when calling web services in .Net

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

When calling HTTPS web services in .NET, the runtime validates the server's SSL/TLS certificate. If the certificate is self-signed, expired, or has a domain mismatch, the call fails with an AuthenticationException or WebException. During development and testing, you may need to bypass this validation. In .NET Framework, you set ServicePointManager.ServerCertificateValidationCallback. In .NET Core/.NET 5+, you configure HttpClientHandler.ServerCertificateCustomValidationCallback. Both approaches should only be used in development — disabling certificate validation in production exposes your application to man-in-the-middle attacks.

.NET Core / .NET 5+ (HttpClient)

csharp
1using System.Net.Http;
2
3// Create handler that bypasses SSL validation
4var handler = new HttpClientHandler
5{
6    ServerCertificateCustomValidationCallback =
7        HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
8};
9
10var client = new HttpClient(handler);
11var response = await client.GetAsync("https://self-signed.example.com/api/data");
12var content = await response.Content.ReadAsStringAsync();

DangerousAcceptAnyServerCertificateValidator is a built-in callback that accepts any certificate. The name intentionally signals that this is unsafe for production.

Custom Validation Callback

csharp
1using System.Net.Http;
2using System.Net.Security;
3using System.Security.Cryptography.X509Certificates;
4
5var handler = new HttpClientHandler
6{
7    ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
8    {
9        // Accept if no errors
10        if (errors == SslPolicyErrors.None)
11            return true;
12
13        // Accept a specific self-signed certificate by thumbprint
14        if (cert?.Thumbprint == "A1B2C3D4E5F6...")
15            return true;
16
17        // Log and reject everything else
18        Console.WriteLine($"SSL error: {errors}, cert: {cert?.Subject}");
19        return false;
20    }
21};
22
23var client = new HttpClient(handler);

A custom callback lets you accept specific certificates (by thumbprint or subject) while rejecting others. This is safer than accepting all certificates.

.NET Framework (ServicePointManager)

csharp
1using System.Net;
2using System.Net.Security;
3using System.Security.Cryptography.X509Certificates;
4
5// Global setting — affects ALL requests in the application
6ServicePointManager.ServerCertificateValidationCallback =
7    (sender, certificate, chain, sslPolicyErrors) => true;
8
9// Make the request
10var client = new WebClient();
11string result = client.DownloadString("https://self-signed.example.com/api");
12
13// More targeted: only bypass for specific hosts
14ServicePointManager.ServerCertificateValidationCallback =
15    (sender, certificate, chain, errors) =>
16    {
17        if (errors == SslPolicyErrors.None)
18            return true;
19
20        // Only bypass for dev server
21        if (sender is HttpWebRequest request &&
22            request.RequestUri.Host == "dev.internal.example.com")
23            return true;
24
25        return false;
26    };

ServicePointManager.ServerCertificateValidationCallback is a global static property — it affects every HTTPS request in the process. This is the .NET Framework approach; .NET Core should use HttpClientHandler instead.

WCF Client

csharp
1using System.ServiceModel;
2using System.Net;
3using System.Net.Security;
4
5// For WCF clients, set the global callback before creating the client
6ServicePointManager.ServerCertificateValidationCallback =
7    (sender, cert, chain, errors) => true;
8
9var binding = new BasicHttpsBinding();
10var endpoint = new EndpointAddress("https://self-signed.example.com/Service.svc");
11var client = new MyServiceClient(binding, endpoint);
12
13var result = await client.GetDataAsync(42);

Environment-Based Configuration

csharp
1using Microsoft.Extensions.DependencyInjection;
2using Microsoft.Extensions.Hosting;
3
4// In Program.cs or Startup.cs
5builder.Services.AddHttpClient("InternalApi", client =>
6{
7    client.BaseAddress = new Uri("https://internal-service.local/");
8})
9.ConfigurePrimaryHttpMessageHandler(() =>
10{
11    var handler = new HttpClientHandler();
12
13    if (builder.Environment.IsDevelopment())
14    {
15        // Only bypass in development
16        handler.ServerCertificateCustomValidationCallback =
17            HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
18    }
19
20    return handler;
21});
22
23// Usage via IHttpClientFactory
24public class MyService
25{
26    private readonly HttpClient _client;
27
28    public MyService(IHttpClientFactory factory)
29    {
30        _client = factory.CreateClient("InternalApi");
31    }
32
33    public async Task<string> GetDataAsync()
34    {
35        var response = await _client.GetAsync("/api/data");
36        return await response.Content.ReadAsStringAsync();
37    }
38}

Using IHttpClientFactory with environment checks ensures SSL bypass only applies in development and only to specific named clients.

Adding a Self-Signed Certificate as Trusted

csharp
1// Instead of bypassing validation, trust the specific certificate
2
3// Linux/Docker: add cert to trusted store
4// cp my-cert.crt /usr/local/share/ca-certificates/
5// update-ca-certificates
6
7// Windows: use certmgr or PowerShell
8// Import-Certificate -FilePath .\my-cert.crt -CertStoreLocation Cert:\LocalMachine\Root
9
10// Programmatically in .NET
11var handler = new HttpClientHandler();
12handler.ClientCertificates.Add(
13    new X509Certificate2("client-cert.pfx", "password"));

Trusting the certificate at the OS level or certificate store is safer than bypassing validation entirely.

Common Pitfalls

  • Using ServicePointManager in .NET Core: ServicePointManager.ServerCertificateValidationCallback has no effect in .NET Core/.NET 5+. It only works in .NET Framework. Use HttpClientHandler.ServerCertificateCustomValidationCallback instead.
  • Leaving bypass enabled in production: Disabling certificate validation in production allows man-in-the-middle attacks. Use environment checks (IsDevelopment()) or compiler directives (#if DEBUG) to ensure the bypass only applies in development.
  • Global callback affecting all requests: ServicePointManager.ServerCertificateValidationCallback applies to every HTTPS request in the process, including third-party libraries and internal .NET calls. Use HttpClientHandler per-client instead of the global callback.
  • Not checking the specific certificate: Accepting all certificates (return true) is the least secure approach. If possible, validate the certificate thumbprint or subject to accept only the specific self-signed certificate you expect.
  • Ignoring the real fix: The best solution is usually to install a proper certificate. Use Let's Encrypt for free trusted certificates, or add your self-signed CA to the machine's trusted root store. Bypassing validation should be a temporary development measure, not a permanent solution.

Summary

  • .NET Core/.NET 5+: use HttpClientHandler.ServerCertificateCustomValidationCallback per client
  • .NET Framework: use ServicePointManager.ServerCertificateValidationCallback (global, affects all requests)
  • Gate SSL bypass with IsDevelopment() or #if DEBUG to prevent production exposure
  • Prefer trusting the specific certificate (by thumbprint or CA) over accepting all certificates
  • The best long-term fix is a proper certificate from a trusted CA or adding your CA to the trust store

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.