search
csharp star Featured

Fix: HTTPS development certificate not trusted error in ASP.NET Core applications

Learn how to fix the 'HTTPS development certificate not trusted' error in ASP.NET Core applications. This comprehensive guide covers certificate installation, trust management, and proper HTTPS configuration.

person By Gautam Sharma
calendar_today January 8, 2026
schedule 21 min read
ASP.NET Core HTTPS Certificate Error Development SSL Trust

The ‘HTTPS development certificate not trusted’ error is a common ASP.NET Core issue that occurs when the development HTTPS certificate generated by .NET is not properly trusted by the operating system or browser. This error typically happens when running ASP.NET Core applications with HTTPS enabled, causing browsers to display security warnings or refuse connections. The error prevents proper testing of HTTPS functionality during development and can disrupt the development workflow.

This comprehensive guide explains what causes this error, why it happens, and provides multiple solutions to fix it in your ASP.NET Core projects with clean code examples and directory structure.


What is the HTTPS Development Certificate Not Trusted Error?

The “HTTPS development certificate not trusted” error occurs when:

  • The development certificate is not installed in the trusted certificate store
  • Certificate generation fails during project startup
  • Browser doesn’t recognize the development certificate authority
  • Certificate files are corrupted or missing
  • Operating system certificate trust is not properly configured
  • Antivirus software blocks certificate installation
  • Multiple certificate authorities conflict

Common Error Messages:

  • NETSDK1149: Failed to generate a development HTTPS certificate.
  • dotnet: The required certificate is not installed or not trusted.
  • Browser security warning: "Your connection is not private"
  • ERR_CERT_AUTHORITY_INVALID
  • NETSDK1013: The specified certificate file could not be found
  • System.Security.Cryptography.CryptographicException: The certificate is not valid for the usage intended

Understanding the Problem

The HTTPS development certificate error occurs because ASP.NET Core uses a self-signed development certificate for HTTPS during development. This certificate needs to be trusted by the operating system and browsers to avoid security warnings. The .NET SDK provides the dotnet dev-certs command to generate and install these certificates, but various factors can prevent proper installation or trust establishment.

Typical ASP.NET Core Project Structure:

MyAspNetApp/
├── MyAspNetApp.sln
├── src/
│   ├── MyAspNetApp/
│   │   ├── Program.cs
│   │   ├── Startup.cs
│   │   ├── appsettings.json
│   │   ├── appsettings.Development.json
│   │   ├── Properties/
│   │   │   └── launchSettings.json
│   │   ├── Controllers/
│   │   │   └── HomeController.cs
│   │   ├── wwwroot/
│   │   ├── MyAspNetApp.csproj
│   │   └── Program.cs
│   └── MyAspNetApp.Tests/
│       ├── UnitTests.cs
│       └── MyAspNetApp.Tests.csproj
├── global.json
└── README.md

Solution 1: Generate and Trust Development Certificate

The most common solution is to properly generate and install the development certificate.

❌ Without Proper Certificate Generation:

// Program.cs - ❌ Without proper HTTPS configuration
var builder = WebApplication.CreateBuilder(args);

// ❌ This might fail if certificate is not trusted
builder.WebHost.UseUrls("https://localhost:5001");

var app = builder.Build();

app.UseHttpsRedirection();
app.MapGet("/", () => "Hello World!");

app.Run();

✅ With Proper Certificate Generation:

Program.cs:

using Microsoft.AspNetCore.Server.Kestrel.Core;

var builder = WebApplication.CreateBuilder(args);

// ✅ Configure Kestrel with HTTPS support
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(5000); // HTTP endpoint
    
    options.ListenAnyIP(5001, listenOptions =>
    {
        try
        {
            // ✅ Use HTTPS with development certificate
            listenOptions.UseHttps(); // This will use the development certificate if available
        }
        catch (System.IO.IOException ex)
        {
            // ✅ Handle certificate issues gracefully
            Console.WriteLine($"HTTPS configuration failed: {ex.Message}");
            Console.WriteLine("Make sure to run 'dotnet dev-certs https --trust' to install the development certificate");
        }
    });
});

var app = builder.Build();

// ✅ Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    
    // ✅ Redirect HTTP to HTTPS in development if certificate is available
    try
    {
        app.UseHttpsRedirection();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"HTTPS redirection failed: {ex.Message}");
        // Continue without HTTPS redirection if certificate is not trusted
    }
}

app.UseRouting();

app.MapGet("/", () => "Hello World!");
app.MapGet("/health", () => new { Status = "Healthy", Timestamp = DateTime.UtcNow });
app.MapControllers();

app.Run();

Commands to generate and trust certificate:

# ✅ Generate and trust the development certificate
dotnet dev-certs https --clean
dotnet dev-certs https --trust

# ✅ Check certificate status
dotnet dev-certs https --check --verbose

# ✅ List all development certificates
dotnet dev-certs https --export-path

Solution 2: Handle Certificate Issues Programmatically

Implement proper error handling for certificate-related issues.

CertificateHelper.cs:

using System.Security.Cryptography.X509Certificates;
using System.Runtime.InteropServices;

public static class CertificateHelper
{
    public static bool IsDevelopmentCertificateTrusted()
    {
        try
        {
            // ✅ Check if the development certificate is in the trusted store
            using var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            
            var certificates = store.Certificates.Find(
                X509FindType.FindBySubjectName, 
                "localhost", 
                validOnly: false
            );
            
            foreach (X509Certificate2 cert in certificates)
            {
                if (cert.Subject.Contains("localhost") && 
                    cert.Issuer.Contains("ASP.NET Core HTTPS development certificate"))
                {
                    return true;
                }
            }
            
            return false;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error checking certificate trust: {ex.Message}");
            return false;
        }
    }

    public static bool InstallDevelopmentCertificate()
    {
        try
        {
            // ✅ Run the dotnet dev-certs command programmatically
            var process = new System.Diagnostics.Process
            {
                StartInfo = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "cmd" : "sh",
                    Arguments = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) 
                        ? "/c dotnet dev-certs https --trust" 
                        : "-c \"dotnet dev-certs https --trust\"",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                }
            };

            process.Start();
            process.WaitForExit();

            var output = process.StandardOutput.ReadToEnd();
            var error = process.StandardError.ReadToEnd();

            if (process.ExitCode == 0)
            {
                Console.WriteLine("Development certificate installed successfully");
                Console.WriteLine(output);
                return true;
            }
            else
            {
                Console.WriteLine($"Failed to install certificate: {error}");
                return false;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error installing certificate: {ex.Message}");
            return false;
        }
    }

    public static bool GenerateSelfSignedCertificate(string outputPath, string password = "password")
    {
        try
        {
            // ✅ Generate a self-signed certificate for development
            using var rsa = RSA.Create(2048);
            
            var request = new CertificateRequest(
                "CN=localhost",
                rsa,
                HashAlgorithmName.SHA256,
                RSASignaturePadding.Pkcs1
            );
            
            request.CertificateExtensions.Add(
                new X509KeyUsageExtension(X509KeyUsageFlags.KeyEncipherment, true)
            );
            
            request.CertificateExtensions.Add(
                new X509EnhancedKeyUsageExtension(
                    new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, // Server Authentication
                    true
                )
            );
            
            var sanBuilder = new SubjectAlternativeNameBuilder();
            sanBuilder.AddDnsName("localhost");
            sanBuilder.AddIpAddress(System.Net.IPAddress.Loopback);
            sanBuilder.AddIpAddress(System.Net.IPAddress.IPv6Loopback);
            request.CertificateExtensions.Add(sanBuilder.Build(true));
            
            var certificate = request.CreateSelfSigned(
                DateTimeOffset.UtcNow.AddDays(-1),
                DateTimeOffset.UtcNow.AddYears(1)
            );
            
            // ✅ Export with private key
            var exported = certificate.Export(X509ContentType.Pfx, password);
            File.WriteAllBytes(outputPath, exported);
            
            Console.WriteLine($"Self-signed certificate generated: {outputPath}");
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error generating self-signed certificate: {ex.Message}");
            return false;
        }
    }

    public static X509Certificate2? LoadDevelopmentCertificate()
    {
        try
        {
            // ✅ Try to load the development certificate
            var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            
            var certificates = store.Certificates.Find(
                X509FindType.FindBySubjectName,
                "localhost",
                validOnly: false
            );
            
            foreach (X509Certificate2 cert in certificates)
            {
                if (cert.Subject.Contains("localhost") && 
                    cert.Issuer.Contains("ASP.NET Core HTTPS development certificate"))
                {
                    store.Close();
                    return new X509Certificate2(cert.Export(X509ContentType.Pkcs12));
                }
            }
            
            store.Close();
            return null;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error loading development certificate: {ex.Message}");
            return null;
        }
    }

    public static bool ValidateCertificate(X509Certificate2? cert)
    {
        if (cert == null)
        {
            return false;
        }

        try
        {
            // ✅ Validate certificate properties
            if (cert.Subject.Contains("localhost") && 
                cert.Issuer.Contains("ASP.NET Core HTTPS development certificate"))
            {
                var chain = new X509Chain();
                chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
                
                var isValid = chain.Build(cert);
                
                if (!isValid)
                {
                    Console.WriteLine("Certificate validation failed:");
                    foreach (var status in chain.ChainStatus)
                    {
                        Console.WriteLine($"  {status.Status}: {status.StatusInformation}");
                    }
                }
                
                return isValid;
            }
            
            return false;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Certificate validation error: {ex.Message}");
            return false;
        }
    }

    public static string GetCertificateStoreLocation()
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            return "CurrentUser\\Root";
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            return "/etc/ssl/certs/";
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            return "System Keychain";
        }
        
        return "Unknown";
    }

    public static bool IsCertificateInTrustedStore(X509Certificate2 cert)
    {
        try
        {
            var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            
            var storedCerts = store.Certificates.Find(
                X509FindType.FindByThumbprint,
                cert.Thumbprint,
                validOnly: false
            );
            
            store.Close();
            return storedCerts.Count > 0;
        }
        catch
        {
            return false;
        }
    }
}

Solution 3: Configure HTTPS with Fallback Options

Set up HTTPS configuration with fallback options for when certificates aren’t trusted.

Program.cs (Enhanced Configuration):

using Microsoft.AspNetCore.Server.Kestrel.Core;
using System.Security.Cryptography.X509Certificates;

var builder = WebApplication.CreateBuilder(args);

// ✅ Configure Kestrel with HTTPS fallback
builder.WebHost.ConfigureKestrel((context, options) =>
{
    var env = context.HostingEnvironment;
    
    // ✅ Configure HTTP endpoint
    options.ListenAnyIP(5000, listenOptions =>
    {
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
    });
    
    // ✅ Configure HTTPS endpoint with fallback
    options.ListenAnyIP(5001, listenOptions =>
    {
        if (env.IsDevelopment())
        {
            try
            {
                // ✅ Try to use development certificate
                listenOptions.UseHttps();
                Console.WriteLine("HTTPS configured with development certificate");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Development certificate not available: {ex.Message}");
                Console.WriteLine("Run 'dotnet dev-certs https --trust' to install the certificate");
                
                // ✅ Fallback: Continue without HTTPS for this endpoint
                // The application will still work but without HTTPS on this port
            }
        }
        else
        {
            // ✅ Production HTTPS configuration
            var certPath = builder.Configuration["SSL_CERT_PATH"];
            var certPassword = builder.Configuration["SSL_CERT_PASSWORD"];
            
            if (!string.IsNullOrEmpty(certPath) && File.Exists(certPath))
            {
                try
                {
                    var cert = new X509Certificate2(certPath, certPassword);
                    listenOptions.UseHttps(cert);
                    Console.WriteLine("HTTPS configured with production certificate");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Production certificate configuration failed: {ex.Message}");
                    // Continue without HTTPS in production as fallback
                }
            }
        }
    });
    
    // ✅ Configure limits
    options.Limits.MaxConcurrentConnections = 100;
    options.Limits.MaxRequestBodySize = 10 * 1024 * 1024;
});

var app = builder.Build();

// ✅ Configure the HTTP request pipeline with HTTPS handling
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    
    // ✅ Only use HTTPS redirection if certificate is trusted
    if (CertificateHelper.IsDevelopmentCertificateTrusted())
    {
        app.UseHttpsRedirection();
        Console.WriteLine("HTTPS redirection enabled");
    }
    else
    {
        Console.WriteLine("HTTPS redirection disabled - certificate not trusted");
    }
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
    
    // ✅ Use HTTPS in production
    app.UseHttpsRedirection();
}

app.UseRouting();

app.MapGet("/", () => "Hello World!");
app.MapGet("/health", () => new { Status = "Healthy", Environment = app.Environment.EnvironmentName, Timestamp = DateTime.UtcNow });
app.MapControllers();

// ✅ Add startup diagnostics
app.Lifetime.ApplicationStarted.Register(() =>
{
    var isCertTrusted = CertificateHelper.IsDevelopmentCertificateTrusted();
    Console.WriteLine($"=== Application Started ===");
    Console.WriteLine($"Environment: {app.Environment.EnvironmentName}");
    Console.WriteLine($"HTTPS Certificate Trusted: {isCertTrusted}");
    Console.WriteLine($"HTTP Endpoint: http://localhost:5000");
    Console.WriteLine($"HTTPS Endpoint: https://localhost:5001");
    
    if (!isCertTrusted && app.Environment.IsDevelopment())
    {
        Console.WriteLine("\n⚠️  WARNING: HTTPS development certificate is not trusted!");
        Console.WriteLine("Run the following command to fix this:");
        Console.WriteLine("  dotnet dev-certs https --trust");
        Console.WriteLine("Or visit: https://aka.ms/dotnet-https for more information.\n");
    }
});

app.Run();

Solution 4: Handle Different Operating Systems

Properly handle certificate installation on different operating systems.

OSHelper.cs:

using System.Runtime.InteropServices;

public static class OSHelper
{
    public static void InstallCertificateForCurrentOS()
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            InstallCertificateOnWindows();
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            InstallCertificateOnLinux();
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            InstallCertificateOnMacOS();
        }
        else
        {
            Console.WriteLine("Unsupported operating system for certificate installation");
        }
    }

    private static void InstallCertificateOnWindows()
    {
        try
        {
            Console.WriteLine("Installing certificate on Windows...");
            
            // ✅ Use PowerShell to install certificate
            var process = new System.Diagnostics.Process
            {
                StartInfo = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = "powershell",
                    Arguments = "-Command \"dotnet dev-certs https --trust\"",
                    UseShellExecute = true,
                    Verb = "runas", // Run as administrator
                    CreateNoWindow = true
                }
            };

            process.Start();
            process.WaitForExit();

            if (process.ExitCode == 0)
            {
                Console.WriteLine("Certificate installed successfully on Windows");
            }
            else
            {
                Console.WriteLine("Failed to install certificate on Windows. Try running as administrator.");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error installing certificate on Windows: {ex.Message}");
        }
    }

    private static void InstallCertificateOnLinux()
    {
        try
        {
            Console.WriteLine("Installing certificate on Linux...");
            
            // ✅ Different Linux distributions may require different approaches
            var process = new System.Diagnostics.Process
            {
                StartInfo = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = "sh",
                    Arguments = "-c \"dotnet dev-certs https --trust\"",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                }
            };

            process.Start();
            process.WaitForExit();

            var output = process.StandardOutput.ReadToEnd();
            var error = process.StandardError.ReadToEnd();

            if (process.ExitCode == 0)
            {
                Console.WriteLine("Certificate installed successfully on Linux");
                Console.WriteLine(output);
            }
            else
            {
                Console.WriteLine($"Failed to install certificate on Linux: {error}");
                
                // ✅ Provide Linux-specific troubleshooting
                Console.WriteLine("On some Linux distributions, you may need to manually trust the certificate:");
                Console.WriteLine("1. Find the certificate file: dotnet dev-certs https --export-path");
                Console.WriteLine("2. Copy it to the system certificate store");
                Console.WriteLine("3. Update the certificate store: sudo update-ca-certificates");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error installing certificate on Linux: {ex.Message}");
        }
    }

    private static void InstallCertificateOnMacOS()
    {
        try
        {
            Console.WriteLine("Installing certificate on macOS...");
            
            var process = new System.Diagnostics.Process
            {
                StartInfo = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = "sh",
                    Arguments = "-c \"dotnet dev-certs https --trust\"",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                }
            };

            process.Start();
            process.WaitForExit();

            var output = process.StandardOutput.ReadToEnd();
            var error = process.StandardError.ReadToEnd();

            if (process.ExitCode == 0)
            {
                Console.WriteLine("Certificate installed successfully on macOS");
                Console.WriteLine(output);
            }
            else
            {
                Console.WriteLine($"Failed to install certificate on macOS: {error}");
                
                // ✅ Provide macOS-specific troubleshooting
                Console.WriteLine("On macOS, you may need to manually trust the certificate:");
                Console.WriteLine("1. Open Keychain Access application");
                Console.WriteLine("2. Find the 'localhost' certificate in the System keychain");
                Console.WriteLine("3. Right-click and select 'Get Info'");
                Console.WriteLine("4. Expand 'Trust' section");
                Console.WriteLine("5. Select 'Always Trust' for SSL");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error installing certificate on macOS: {ex.Message}");
        }
    }

    public static string GetOSName()
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            return "Windows";
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            return "Linux";
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            return "macOS";
        }
        
        return "Unknown";
    }

    public static string GetCertificateLocation()
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            return "%LOCALAPPDATA%\\ASP.NET\\https";
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            return "$HOME/.aspnet/https";
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            return "$HOME/.aspnet/https";
        }
        
        return "";
    }

    public static void ShowCertificateInstructions()
    {
        var osName = GetOSName();
        var certLocation = GetCertificateLocation();
        
        Console.WriteLine($"=== Certificate Installation Instructions for {osName} ===");
        Console.WriteLine($"Certificate Location: {certLocation}");
        Console.WriteLine();
        Console.WriteLine("To fix the HTTPS development certificate issue:");
        Console.WriteLine("1. Open terminal/command prompt as administrator (Windows) or with sudo (Linux)");
        Console.WriteLine("2. Run the following command:");
        Console.WriteLine("   dotnet dev-certs https --clean");
        Console.WriteLine("   dotnet dev-certs https --trust");
        Console.WriteLine("3. Restart your development server");
        Console.WriteLine();
        Console.WriteLine("Alternative commands:");
        Console.WriteLine("   dotnet dev-certs https --check --verbose  # Check certificate status");
        Console.WriteLine("   dotnet dev-certs https --export-path      # Show certificate path");
        Console.WriteLine("   dotnet dev-certs https --help             # Show all options");
    }
}

Solution 5: Create a Certificate Management Service

Implement a service to manage certificate operations.

Services/CertificateManagementService.cs:

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Security.Cryptography.X509Certificates;

public interface ICertificateManagementService
{
    Task<bool> EnsureCertificateIsTrustedAsync();
    Task<bool> GenerateNewCertificateAsync();
    Task<bool> ValidateCertificateAsync();
    string GetCertificateStatus();
}

public class CertificateManagementService : ICertificateManagementService, IHostedService
{
    private readonly ILogger<CertificateManagementService> _logger;
    private Timer? _timer;

    public CertificateManagementService(ILogger<CertificateManagementService> logger)
    {
        _logger = logger;
    }

    public async Task<bool> EnsureCertificateIsTrustedAsync()
    {
        _logger.LogInformation("Checking HTTPS development certificate trust status...");
        
        var isTrusted = CertificateHelper.IsDevelopmentCertificateTrusted();
        
        if (!isTrusted)
        {
            _logger.LogWarning("HTTPS development certificate is not trusted");
            
            // ✅ Try to install the certificate
            var installed = CertificateHelper.InstallDevelopmentCertificate();
            
            if (installed)
            {
                _logger.LogInformation("HTTPS development certificate installed successfully");
                
                // ✅ Wait a moment for the certificate to be recognized
                await Task.Delay(1000);
                
                // ✅ Verify the installation
                isTrusted = CertificateHelper.IsDevelopmentCertificateTrusted();
                
                if (isTrusted)
                {
                    _logger.LogInformation("HTTPS development certificate is now trusted");
                }
                else
                {
                    _logger.LogError("HTTPS development certificate installation completed but still not trusted");
                }
            }
            else
            {
                _logger.LogError("Failed to install HTTPS development certificate");
            }
        }
        else
        {
            _logger.LogInformation("HTTPS development certificate is already trusted");
        }
        
        return isTrusted;
    }

    public async Task<bool> GenerateNewCertificateAsync()
    {
        _logger.LogInformation("Generating new HTTPS development certificate...");
        
        try
        {
            // ✅ Clean existing certificates
            var cleanProcess = new System.Diagnostics.Process
            {
                StartInfo = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = "dotnet",
                    Arguments = "dev-certs https --clean",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                }
            };

            cleanProcess.Start();
            await cleanProcess.WaitForExitAsync();
            
            if (cleanProcess.ExitCode != 0)
            {
                var error = await cleanProcess.StandardError.ReadToEndAsync();
                _logger.LogError($"Failed to clean certificates: {error}");
                return false;
            }

            // ✅ Generate and trust new certificate
            var trustProcess = new System.Diagnostics.Process
            {
                StartInfo = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = "dotnet",
                    Arguments = "dev-certs https --trust",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                }
            };

            trustProcess.Start();
            await trustProcess.WaitForExitAsync();
            
            var output = await trustProcess.StandardOutput.ReadToEndAsync();
            var error2 = await trustProcess.StandardError.ReadToEndAsync();

            if (trustProcess.ExitCode == 0)
            {
                _logger.LogInformation($"New certificate generated successfully: {output}");
                return true;
            }
            else
            {
                _logger.LogError($"Failed to generate certificate: {error2}");
                return false;
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error generating new certificate");
            return false;
        }
    }

    public async Task<bool> ValidateCertificateAsync()
    {
        var cert = CertificateHelper.LoadDevelopmentCertificate();
        if (cert == null)
        {
            _logger.LogWarning("No development certificate found");
            return false;
        }

        var isValid = CertificateHelper.ValidateCertificate(cert);
        
        if (isValid)
        {
            _logger.LogInformation("Development certificate is valid");
        }
        else
        {
            _logger.LogWarning("Development certificate is not valid");
        }
        
        return isValid;
    }

    public string GetCertificateStatus()
    {
        var isTrusted = CertificateHelper.IsDevelopmentCertificateTrusted();
        var cert = CertificateHelper.LoadDevelopmentCertificate();
        
        var status = new
        {
            IsTrusted = isTrusted,
            IsAvailable = cert != null,
            Subject = cert?.Subject ?? "Not Found",
            Issuer = cert?.Issuer ?? "Not Found",
            ValidFrom = cert?.NotBefore.ToString("yyyy-MM-dd HH:mm:ss") ?? "N/A",
            ValidTo = cert?.NotAfter.ToString("yyyy-MM-dd HH:mm:ss") ?? "N/A",
            Thumbprint = cert?.Thumbprint ?? "N/A"
        };

        return System.Text.Json.JsonSerializer.Serialize(status, new System.Text.Json.JsonSerializerOptions { WriteIndented = true });
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Certificate Management Service starting...");
        
        // ✅ Run certificate check immediately
        _ = Task.Run(async () =>
        {
            await EnsureCertificateIsTrustedAsync();
        }, cancellationToken);
        
        // ✅ Schedule periodic checks
        _timer = new Timer(async _ => await CheckCertificateStatus(), null, TimeSpan.Zero, TimeSpan.FromHours(1));
        
        return Task.CompletedTask;
    }

    private async Task CheckCertificateStatus()
    {
        try
        {
            var isTrusted = CertificateHelper.IsDevelopmentCertificateTrusted();
            if (!isTrusted)
            {
                _logger.LogWarning("Certificate trust status changed - certificate is no longer trusted");
                await EnsureCertificateIsTrustedAsync();
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error checking certificate status");
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Certificate Management Service stopping...");
        _timer?.Dispose();
        return Task.CompletedTask;
    }
}

Working Code Examples

Complete ASP.NET Core Application with Certificate Management:

// Program.cs
using Microsoft.AspNetCore.Server.Kestrel.Core;
using System.Security.Cryptography.X509Certificates;

var builder = WebApplication.CreateBuilder(args);

// ✅ Add certificate management service
builder.Services.AddHostedService<CertificateManagementService>();

// ✅ Configure Kestrel with HTTPS
builder.WebHost.ConfigureKestrel((context, options) =>
{
    var env = context.HostingEnvironment;
    
    // ✅ Configure HTTP endpoint
    options.ListenAnyIP(5000, listenOptions =>
    {
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
    });
    
    // ✅ Configure HTTPS endpoint
    options.ListenAnyIP(5001, listenOptions =>
    {
        if (env.IsDevelopment())
        {
            try
            {
                // ✅ Use development certificate
                listenOptions.UseHttps();
                Console.WriteLine("HTTPS configured with development certificate");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Development certificate not available: {ex.Message}");
            }
        }
        else
        {
            // ✅ Production HTTPS configuration
            var certPath = builder.Configuration["SSL_CERT_PATH"];
            var certPassword = builder.Configuration["SSL_CERT_PASSWORD"];
            
            if (!string.IsNullOrEmpty(certPath) && File.Exists(certPath))
            {
                try
                {
                    var cert = new X509Certificate2(certPath, certPassword);
                    listenOptions.UseHttps(cert);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Production certificate configuration failed: {ex.Message}");
                }
            }
        }
    });
    
    // ✅ Configure limits
    options.Limits.MaxConcurrentConnections = 100;
    options.Limits.MaxRequestBodySize = 10 * 1024 * 1024;
});

var app = builder.Build();

// ✅ Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    
    // ✅ Only use HTTPS redirection if certificate is trusted
    if (CertificateHelper.IsDevelopmentCertificateTrusted())
    {
        app.UseHttpsRedirection();
    }
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
    app.UseHttpsRedirection();
}

app.UseRouting();

app.MapGet("/", () => "Hello World!");
app.MapGet("/health", () => new { Status = "Healthy", Environment = app.Environment.EnvironmentName, Timestamp = DateTime.UtcNow });

// ✅ Certificate management endpoints
app.MapGet("/cert/status", (ICertificateManagementService certService) =>
{
    return certService.GetCertificateStatus();
});

app.MapPost("/cert/regenerate", async (ICertificateManagementService certService) =>
{
    var success = await certService.GenerateNewCertificateAsync();
    return new { Success = success };
});

app.MapControllers();

// ✅ Add startup diagnostics
app.Lifetime.ApplicationStarted.Register(() =>
{
    var isCertTrusted = CertificateHelper.IsDevelopmentCertificateTrusted();
    Console.WriteLine($"=== Application Started ===");
    Console.WriteLine($"Environment: {app.Environment.EnvironmentName}");
    Console.WriteLine($"HTTPS Certificate Trusted: {isCertTrusted}");
    Console.WriteLine($"HTTP Endpoint: http://localhost:5000");
    Console.WriteLine($"HTTPS Endpoint: https://localhost:5001");
    
    if (!isCertTrusted && app.Environment.IsDevelopment())
    {
        Console.WriteLine("\n⚠️  WARNING: HTTPS development certificate is not trusted!");
        Console.WriteLine("Run the following command to fix this:");
        Console.WriteLine("  dotnet dev-certs https --trust");
        Console.WriteLine("Or visit: https://aka.ms/dotnet-https for more information.\n");
    }
    
    // ✅ Show OS-specific instructions
    OSHelper.ShowCertificateInstructions();
});

app.Run();

Launch Settings Configuration:

// Properties/launchSettings.json
{
  "profiles": {
    "MyAspNetApp": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

Unit Test Example:

// MyAspNetApp.Tests/UnitTests.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading.Tasks;

namespace MyAspNetApp.Tests
{
    [TestClass]
    public class CertificateTests
    {
        [TestMethod]
        public async Task CertificateHelper_IsDevelopmentCertificateTrusted_ReturnsBool()
        {
            // ✅ Test certificate trust status
            var result = CertificateHelper.IsDevelopmentCertificateTrusted();
            
            // ✅ This should return a boolean without throwing
            Assert.IsInstanceOfType(result, typeof(bool));
        }

        [TestMethod]
        public async Task CertificateHelper_LoadDevelopmentCertificate_ReturnsCertificateOrNull()
        {
            // ✅ Test certificate loading
            var cert = CertificateHelper.LoadDevelopmentCertificate();
            
            // ✅ Should return null or a valid certificate
            Assert.IsTrue(cert == null || cert.Handle != IntPtr.Zero);
        }

        [TestMethod]
        public async Task CertificateHelper_ValidateCertificate_ValidCert_ReturnsTrue()
        {
            // ✅ Test certificate validation
            var cert = CertificateHelper.LoadDevelopmentCertificate();
            var result = CertificateHelper.ValidateCertificate(cert);
            
            // ✅ Should return a boolean
            Assert.IsInstanceOfType(result, typeof(bool));
        }

        [TestMethod]
        public async Task OSHelper_GetOSName_ReturnsValidName()
        {
            // ✅ Test OS detection
            var osName = OSHelper.GetOSName();
            
            // ✅ Should return a valid OS name
            Assert.IsTrue(!string.IsNullOrEmpty(osName));
        }

        [TestMethod]
        public async Task CertificateManagementService_EnsureCertificateIsTrustedAsync_ReturnsBool()
        {
            // ✅ Test certificate service
            var service = new CertificateManagementService(Mock.Of<ILogger<CertificateManagementService>>());
            var result = await service.EnsureCertificateIsTrustedAsync();
            
            // ✅ Should return a boolean
            Assert.IsInstanceOfType(result, typeof(bool));
        }
    }
}

Best Practices for Certificate Management

1. Always Check Certificate Status

// ✅ Check certificate status before enabling HTTPS
if (CertificateHelper.IsDevelopmentCertificateTrusted())
{
    app.UseHttpsRedirection();
}

2. Handle Certificate Issues Gracefully

// ✅ Handle certificate issues without crashing
try
{
    listenOptions.UseHttps();
}
catch (Exception ex)
{
    Console.WriteLine($"HTTPS configuration failed: {ex.Message}");
    // Continue without HTTPS
}

3. Use Environment-Specific Configuration

// ✅ Different configurations for different environments
if (env.IsDevelopment())
{
    // Development certificate handling
}
else
{
    // Production certificate handling
}

4. Implement Certificate Validation

// ✅ Validate certificates before use
if (CertificateHelper.ValidateCertificate(cert))
{
    // Use the certificate
}

5. Provide Clear Instructions

// ✅ Provide clear instructions for certificate issues
if (!isCertTrusted)
{
    Console.WriteLine("Run 'dotnet dev-certs https --trust' to fix this issue");
}

Debugging Steps

Step 1: Check Certificate Status

# Check if certificate is installed and trusted
dotnet dev-certs https --check --verbose

Step 2: Clean and Regenerate Certificate

# Clean existing certificates
dotnet dev-certs https --clean

# Generate and trust new certificate
dotnet dev-certs https --trust

Step 3: Verify Certificate Location

# Check certificate export path
dotnet dev-certs https --export-path

Step 4: Check Certificate Store

# On Windows, check certificate in MMC
# On macOS, check in Keychain Access
# On Linux, check in certificate store

Step 5: Use Verbose Logging

// Enable verbose logging for certificate operations
Console.WriteLine($"Certificate status: {CertificateHelper.IsDevelopmentCertificateTrusted()}");

Common Mistakes to Avoid

1. Not Installing Certificate with Trust

# ❌ Don't just generate, also trust the certificate
dotnet dev-certs https  # ❌ Only generates
dotnet dev-certs https --trust  # ✅ Generates and trusts

2. Running Without Administrator Privileges

# ❌ Don't run without proper privileges on Windows
dotnet dev-certs https --trust  # ❌ May fail without admin rights

3. Ignoring Certificate Validation

// ❌ Don't ignore certificate validation
try
{
    listenOptions.UseHttps(); // ❌ May throw if certificate is invalid
}
catch
{
    // ❌ Silent failure
}

4. Not Handling Different Operating Systems

// ❌ Don't assume same behavior across OS
// Need OS-specific handling for certificate installation

5. Using Production Certificates in Development

// ❌ Don't use production certificates for development
// Use development certificates for development environment

Performance Considerations

1. Minimize Certificate Operations

// ✅ Cache certificate validation results
private static bool? _certificateTrustedCache = null;
if (_certificateTrustedCache == null)
{
    _certificateTrustedCache = CertificateHelper.IsDevelopmentCertificateTrusted();
}

2. Use Efficient Certificate Loading

// ✅ Load certificates once and reuse
private static X509Certificate2? _cachedCertificate = null;
if (_cachedCertificate == null)
{
    _cachedCertificate = CertificateHelper.LoadDevelopmentCertificate();
}

3. Avoid Frequent Certificate Regeneration

// ✅ Don't regenerate certificates frequently
// Only regenerate when necessary

Security Considerations

1. Validate Certificate Trust

// ✅ Always validate certificate trust before use
if (!CertificateHelper.IsDevelopmentCertificateTrusted())
{
    throw new InvalidOperationException("Certificate is not trusted");
}

2. Secure Certificate Storage

// ✅ Store certificates securely
// Don't hardcode certificate paths or passwords

3. Handle Certificate Expiration

// ✅ Check certificate validity period
var cert = CertificateHelper.LoadDevelopmentCertificate();
if (cert != null && (DateTime.Now < cert.NotBefore || DateTime.Now > cert.NotAfter))
{
    // Certificate is expired or not yet valid
}

Testing Certificate Scenarios

1. Test Certificate Installation

[TestMethod]
public async Task CertificateInstallation_InstallsSuccessfully_ReturnsTrue()
{
    var result = CertificateHelper.InstallDevelopmentCertificate();
    Assert.IsTrue(result);
}

2. Test Certificate Trust Status

[TestMethod]
public async Task CertificateTrust_ChecksStatus_ReturnsBool()
{
    var result = CertificateHelper.IsDevelopmentCertificateTrusted();
    Assert.IsInstanceOfType(result, typeof(bool));
}

3. Test Certificate Validation

[TestMethod]
public async Task CertificateValidation_ValidCert_ReturnsTrue()
{
    var cert = CertificateHelper.LoadDevelopmentCertificate();
    var result = CertificateHelper.ValidateCertificate(cert);
    Assert.IsTrue(result);
}

Alternative Solutions

1. Use HTTP for Development

// ✅ Use HTTP during development if HTTPS is problematic
if (env.IsDevelopment())
{
    builder.WebHost.UseUrls("http://localhost:5000");
}

2. Self-Signed Certificate Generation

// ✅ Generate self-signed certificates programmatically
CertificateHelper.GenerateSelfSignedCertificate("dev-cert.pfx", "password");

3. Reverse Proxy Configuration

# Use nginx as reverse proxy to handle HTTPS
server {
    listen 443 ssl;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location / {
        proxy_pass http://localhost:5000;
    }
}

Migration Checklist

  • Run dotnet dev-certs https --clean to remove old certificates
  • Run dotnet dev-certs https --trust to install trusted certificate
  • Verify certificate status with dotnet dev-certs https --check --verbose
  • Update application to handle certificate trust status gracefully
  • Test HTTPS functionality after certificate installation
  • Verify browser accepts the development certificate
  • Update deployment scripts to handle certificate requirements
  • Document certificate management procedures for team members

Conclusion

The ‘HTTPS development certificate not trusted’ error is a common but solvable ASP.NET Core issue that typically stems from certificate installation or trust configuration problems. By following the solutions provided in this guide—properly generating and trusting certificates, implementing graceful error handling, configuring environment-specific settings, and following best practices—you can effectively resolve this error and ensure your ASP.NET Core applications work properly with HTTPS during development.

The key is to understand that development certificates require explicit trust installation, implement defensive programming practices, use appropriate configurations for different environments, and maintain clean, well-organized code. With proper certificate management, your ASP.NET Core applications will be more resilient and provide a better development experience.

Remember to test your changes thoroughly, follow ASP.NET Core best practices for HTTPS configuration, implement proper error handling, and regularly verify your certificate configurations to ensure your applications maintain the best possible architecture and avoid common development certificate issues.

Gautam Sharma

About Gautam Sharma

Full-stack developer and tech blogger sharing coding tutorials and best practices

Related Articles

csharp

Fix: Unable to start Kestrel error in ASP.NET

Learn how to fix the 'Unable to start Kestrel' error in ASP.NET Core applications. This comprehensive guide covers port conflicts, SSL certificates, configuration issues, and proper Kestrel setup.

January 8, 2026
csharp

Fix: Cannot consume scoped service from singleton error in C#

Learn how to fix the 'Cannot consume scoped service from singleton' error in C# dependency injection. This comprehensive guide covers service lifetimes, proper registration patterns, and architectural solutions.

January 8, 2026
csharp

Fix: CORS Error in ASP.NET Core - Complete Cross-Origin Guide

Learn how to fix CORS errors in ASP.NET Core applications. This comprehensive guide covers CORS configuration, policy setup, and proper cross-origin request handling techniques.

January 8, 2026