How to implement Certificate Authentication in ASP.NET Core

How to implement Certificate Authentication in ASP.NET Core

Certificate-based Authentication uses Digital Certificate to identify a client’s request and then grants it the access to a resource, network, application, etc. Certificate Authentication provides added security to web applications and Web APIs. Here I will tell how to implement Certificate Authentication in ASP.NET Core.

Certificate Authentication is a great way to secure your ASP.NET Core APIs. I have provided the full source that can be downloaded at the end of this tutorial.

PowerShell Commands to create Certificates

Certificate Authentication requires 2 types of Certificates, these are:

  • Certification Authority (CA)
  • Child Certificate

Now let us create both these certificates in PowerShell.

Creating Certification Authority (CA) in PowerShell

First open the PowerShell as an adminstrator. Then run the following 3 commands one by one.

Command 1: Create Self Signed Certificate
New-SelfSignedCertificate -DnsName "localhost", "localhost" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "Rlocalhost" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature

I have kept the value of -DnsName parameter as localhost which is absolutely right since I am securing the app running locally. In production you will have to use the value of your domain. Example -DnsName "yogihosting".

This command will create the self-signed Certificate Authority and provide it’s thumbprint. Keep this thumbprint safe as we will use it to create child certificate.

certificate  thumbprint
Command 2: Set the password for the Certificate

I am keeping the password 1234.

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
Command 3: Export the Certificate in a PFX file

We will now use the password which we set earlier and use it along with the thumbprint to export the certificate in a .pfx file.

Run the below command but before that change the text "thumbprint" with the thumbprint which you got earlier.

Get-ChildItem -Path cert:\localMachine\my\"thumbprint" | Export-PfxCertificate -FilePath D:\root.pfx -Password $mypwd
export pfx command

The command will export the certificate authority file called root.pfx on the “D” drive.

Creating Child Certificate in PowerShell

Let us create Child Certificate from root CA. So run the following 4 commands one by one. Note that:

  • In the first command change the text "ca thumbprint" with the thumbprint of root certificate which you got earlier.
  • After running the second command you will get the thumbprint of the child certificate. You have to change the text "thumbprint" in the fourth command with this thumbprint.

These 4 commands are given below.

$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"ca thumbprint" )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "localhost" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "Clocalhost"

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

Get-ChildItem -Path cert:\localMachine\my\"thumbprint" | Export-PfxCertificate -FilePath D:\child.pfx -Password $mypwd

The child certificate file called child.pfx will be created on the “D” drive.

In the following image I have shown both the certificate files that are created on my D drive.

cerficates pfx file

Implementing Certificate Based Authentication

In your ASP.NET Core app, first add the package called Microsoft.AspNetCore.Authentication.Certificate from NuGet.

Next, add a validation class whose role is to validate the child Certificates of the clients which are making the request.

public class MyCertificateValidationService
    public bool ValidateCertificate(X509Certificate2 clientCertificate)
        string[] allowedThumbprints = { "21A6E47A962C0E80A59517691FFA1D0500E3E548", "87A6E47A962C0E80A59517691FFA1D0500E3E548", "78A6E47A962C0E80A59517691FFA1D0500E3E548" };
        if (allowedThumbprints.Contains(clientCertificate.Thumbprint))
            return true;

        return false;

The string array allowedThumbprints contains 3 thumbprints of the child certificates. Make sure to put the child certificate thumbprint else you will fail to authorize.

In real world app you will be storing the child certificates thumbprints on the database and filling the string array with these values dynamically. So if there are 100 thumbprints on the database then only those 100 client certificates will be authorized.

Next, on the Startup file ConfigureServices method, do 2 things:

  • 1. Register this validation class using AddTransient method.
  • 2. Tell app to use Certificate Authentication with the AddAuthentication method.

In the AddAuthentication() method provide a delegate for OnCertificateValidated and OnAuthenticationFailed events. These events will be called if certificate validation passes or fails.

Check the below highlighted code:

public void ConfigureServices(IServiceCollection services)

        .AddCertificate(options =>
            options.AllowedCertificateTypes = CertificateTypes.SelfSigned;
            options.Events = new CertificateAuthenticationEvents
                OnCertificateValidated = context =>
                    var validationService = context.HttpContext.RequestServices.GetService<MyCertificateValidationService>();

                    if (validationService.ValidateCertificate(context.ClientCertificate))
                        context.Fail("invalid cert");

                    return Task.CompletedTask;
                OnAuthenticationFailed = context =>
                    context.Fail("invalid cert");
                    return Task.CompletedTask;

Note that the code – options.AllowedCertificateTypes = CertificateTypes.SelfSigned must specifiy the certificate type which should be self signed in our case. It can have 3 values: All, Chained and SelfSigned.

I covered ASP.NET Core Action method in full details in my tutorial. I am sure you will discover new ways to work with them in your apps.
Next, add app.UseAuthentication() and app.UseAuthorization() methods inside the Configure method of startup.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)



    app.UseEndpoints(endpoints =>
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");

Configure Kestrel to require certificates

Finally, you have to configure Kestrel so that the application always require certificates. This is done by adding the below code to the Program.cs file:

public static IHostBuilder CreateHostBuilder(string[] args)
    return Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
            webBuilder.ConfigureKestrel(o =>
                o.ConfigureHttpsDefaults(o => o.ClientCertificateMode = ClientCertificateMode.RequireCertificate);

This completes the integration.

Test Certificate Authentication in Web API

In my Certificate Authentication configured app, I created a simple web api controller which returns a text – “Welcome to Narnia”.

using Microsoft.AspNetCore.Mvc;

namespace Test1.Controllers
    public class HomeController : ControllerBase
        public string Get() => "Welcome to Narnia";

Next on Visual Studio select the kestrel option from the run dropdown. I have shown this in the below image. This makes sure that when I run the app on visual studio then kestrel should run it instead of IIS.

select kestrel

Now run your app on visual studio and open the URL of the Web API which in my case is – https://localhost:5001/api/Home . You will see you cannot access the api as it is requiring a certificate for authentication. See the error message given by the browser.

client certificate required
Adding Root CA to CertMgr

Windows uses a utility called CertMgr to manage certificates. Search for “CertMgr” or “Manage Computer Certificates” in the windows search to open this utility. Next, right click on the “Certificates” folder which is under the “Trusted Root Certification Authorities” and select All Tasks ➤ Import and browse to the root.pfx file on the D drive.

certmgr adding certificate

Click on the Next button to reach the next screen where you are asked to enter the private key (password). Recall we used “1234” as the password.

certmgr ca password

Continue the process and your root CA certificate will be added.

Adding Child Certificate in Chrome Browser

Now we will add the child certificate to chrome browser. So go to settings and then click the Security section under “Privacy and security”. Here you will find Manage Certificates, click on it to open a dialog window.

In this window make sure you are on the “Personal” tab and then click the Import button. Simply import the child.pfx file. As previously, enter the password 1234 when asked.

import certificate chrome

Now once again run your app on Visual Studio and open the url of the web api. This time chrome will ask you to select the child certificate.

select certificate chrome

Click the OK button and this time you will be able to access the web api. See the below image which confirms this.

web api certificate authentication

Implement HttpClient with Certificate Authentication

When using HttpClient class to call web apis (that are secured by certification authentciation) you have to add the client certificate to the request, you do this with HttpClientHandler. Check the highlighted code given below.

public async Task<IActionResult> Index()
    var cert = new X509Certificate2(Path.Combine(env.ContentRootPath, "child.pfx"), "1234");
    var handler = new HttpClientHandler();

    string apiResponse = "";

    using (var httpClient = new HttpClient(handler))
        using (var response = await httpClient.GetAsync("https://localhost:5001/api/Home"))
            apiResponse = await response.Content.ReadAsStringAsync();
    return View((object)apiResponse);

Download full source codes:


Congrats you have successfully implemented the Certificate Authentication system in your app. You app now becomes more secure than before.
Next tutorials of great interest:


  • linkedin
  • reddit


I hope you enjoyed reading this tutorial. If it helped you then consider buying a cup of coffee for me. This will help me in writing more such good tutorials for the readers. Thank you. Buy Me A Coffee donate


  1. Yong Seo says:

    Thanks much for your wonderful tutorial for the client certificate. I am having a problem connecting to the service from my console client.

    var cert = new X509Certificate2(@”c:\…\root_localhost.pfx”, “1234”);
    var handler = new HttpClientHandler();
    var client = new HttpClient(handler);
    var request = new HttpRequestMessage()
    RequestUri = new Uri(“https://localhost”),
    Method = HttpMethod.Get,
    var response = await client.SendAsync(request);
    if (!response.IsSuccessStatusCode)
    //I am getting 403 always

    I checked “Require SSL” on IIS SSL Ssettings and checked “Client Certirficate” to be “Required”.

    I can’t figure out how to make it work.
    Any help and advice are appreciated.

    Thank again.

  2. nizar elouaer says:

    Thanks for the post. I implanted my certificate authentication based on your post. When I run my application in my windows 10 machine everything works correctly. However when I use docker, call my url (for example https://localhost:5001/api) I am having e err_connection_closed issue. Any suggestion please ? Thank you

    1. yogihosting says:

      Most probably the reason can be the Certificate is not allowed by the browser. You should try regenerating a new Root and client certificates from the Powershell command. Hope it helps you.


  3. nizar elouaer says:

    Hello. thank you for the post. I used the tutorial to add certifccate authentication in my app, it owrks perfectly on Windows. However when I execute the app on Ubuntu, I am always having an “ERR_CONNECTION_CLOSED”. I generated a certificate using openssl on my ubuntu machine but I am still having the same issue.
    PS: if I comment the lines
    .ConfigureKestrel(options =>
    options.ConfigureHttpsDefaults(opt =>
    opt.ClientCertificateMode =
    I am able to get a response, however the request has no certificate.

    Any idea ? Thank you

  4. Jonathan Conley says:

    I run sample code and get Access to localhost was denied You don’t have authorization to view this page.
    HTTP ERROR 403

Leave a Reply

Your email address will not be published. Required fields are marked *