Client certifiate authenticaiton of .NET 6.0 Web API

Summary

In this article, I would share a .NET 6.0 Web API sample code that supports Client certificate authentication. The sample code utilizes the build-in feature of .NET Microsoft.AspNetCore.Authentication.Certificate that is SIMILAR to C…


This content originally appeared on DEV Community and was authored by Kohei Kawata

Summary

In this article, I would share a .NET 6.0 Web API sample code that supports Client certificate authentication. The sample code utilizes the build-in feature of .NET Microsoft.AspNetCore.Authentication.Certificate that is SIMILAR to Certificate Request of Handshake Protocol written in The Transport Layer Security Protocol (RFC5246).

TOC

  • Concept
    • Web server - Local machine (Kestrel)
    • Web server - Azure App Service
    • Authentication event
    • Certificate validation
    • Configuration - Local machine
    • Configuration - Azure App Service
  • Sample request
  • Self-signed certificate

Concept

  • Web Server requires a client certificate and validate the certificate is trusted during TLS handshake.
  • CertificateAuthenticationOptions handler checks the certificate type.
  • CertificateValidationService validates the pfx file or thumbprint.
  • Controller has to have [Authorize] attribute because it deals with the context determined in TLS handshake and Authentication/Authorization middleware.

Image description

Web server - Local machine (Kestrel)

  • Configure Kestrel server for a local run so it requires a client certificate during TLS handshake
  • Microsoft.AspNetCore.Server.Kestrel.Https.ClientCertificateMode has options such as RequireCertificate and AllowCertificate. Once you set RequireCertificate, any request without a client certificate is declined.
  • A self-signed certificate does not work without AllowAnyClientCertificate() method.

Program.cs

builder.Services.Configure<KestrelServerOptions>(options =>
{
    options.ConfigureHttpsDefaults(options =>
    {
        options.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
        options.AllowAnyClientCertificate();
    });

});

Web server - Azure App Service

  • When the application code is deployed in Azure App Service, it requires another Web Server configuration than Kestrel in Program.cs.
  • Azure App Service has configuration that accepts and requires a client certificate in the request from the client application.
  • Set clientCertEnabled: true and clientCertMode: 'Required' in your bicep file.
  • It looks you do not need to specify self-signed certificate for Azure App Service.

Bicep example

resource AppServiceCert 'Microsoft.Web/sites@2021-03-01' = {
  name: appsrv_name_cert
  location: location
  kind: 'app'
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    serverFarmId: AppServicePlanCert.id
    httpsOnly: true
    clientCertEnabled: true
    clientCertMode: 'Required'
    siteConfig: {
      netFrameworkVersion: '6.0'
      http20Enabled: true
      minTlsVersion: '1.2'
    }
  }
}

Authentication event

  • An event handler CertificateAuthenticationEvents is triggered during a TLS handshake, which is written with builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) in Program.cs.
  • A self-signed certificate requires CertificateAuthenticationOptions.AllowedCertificateTypes property to be All or SelfSigned.
  • The CertificateAuthenticationOptions handler calls CertificateValidationService and set the context success or fail.
  • If the validation fails, it returns 403 forbidden during the TLS handshake before it reaches .NET application.

Program.cs

builder.Services.AddAuthentication(
        CertificateAuthenticationDefaults.AuthenticationScheme)
    .AddCertificate(options =>
    {
        options.AllowedCertificateTypes = CertificateTypes.All;
        options.Events = new CertificateAuthenticationEvents
        {
            OnCertificateValidated = context =>
            {
                var validationService = context.HttpContext.RequestServices
                    .GetRequiredService<ICertificateValidationService>();
                if (validationService.ValidateCertificate(context.ClientCertificate))
                {
                    context.Success();
                }
                else
                {
                    context.Fail("Invalid certificate");
                }
                return Task.CompletedTask;
            }
        };
    });

Certificate validation

  • CertificateValidationService handles the certificate validation and returns true/false to CertificateAuthenticationOptions handler.
  • To validate an incoming client certificate, the Web API app config has Pfx file path and Pfx password, or the certificate thumbprint.
  • If the Web API instance does not have the Pfx file, for example, if it is deployed in Azure App Service, the service validates if the incoming certificate thumbprint is identical with the one in the app config.

CertificateValidationService

public bool ValidateCertificate(X509Certificate2 clientCertificate)
{
    X509Certificate2 expectedCertificate;
    string pfxFilePath = this.configuration.GetValue<string>("Certificate:PfxFilePath");
    string pfxFilePassword = this.configuration.GetValue<string>("Certificate:PfxFilePassword");

    if (File.Exists(Path.Combine(Directory.GetCurrentDirectory(), pfxFilePath)))
    {
        expectedCertificate = new X509Certificate2(
            Path.Combine(Directory.GetCurrentDirectory(), pfxFilePath), pfxFilePassword);
        return clientCertificate.Thumbprint == expectedCertificate.Thumbprint;
    }
    else
    {
        return clientCertificate.Thumbprint == this.configuration.GetValue<string>("Certificate:Thumbprint");
    }
}

Configuration - Local machine

For local run, you will set the Pfx file path and password or thumbprint in appsettings.json or appsettings.Development.json

appsettings.json example

"Certificate": {
   "PfxFilePath": "certificates/sample.pfx",
   "PfxFilePassword": "{Pfx file password if needed}",
   "Thumbprint": "6B132..."
}

Configuration - Azure App Service

  • It is difficult to have the Pfx file in Azure App Service, and then it can validate with the thumbprint.
  • The thumbprint should be stored in Azure Key Vault and the App Service extracts it through Key Vault reference.

Bicep example

resource AppServiceConfigCert 'Microsoft.Web/sites/config@2021-03-01' = {
  name: '${AppServiceCert.name}/appsettings'
  properties: {
    'Certificate:PfxFilePath': ''
    'Certificate:PfxFilePassword': ''
    'Certificate:Thumbprint': '@Microsoft.KeyVault(VaultName=${kv_name};SecretName=${kvsecret_name_cert_thumbprint})'
    'WEBSITE_RUN_FROM_PACKAGE': 1
  }
}

Sample request

  • It seems bash does not have a feature to send a pfx file. So I tried with a cert file and private key.
  • Powershell supports sending a pfx file. It requires a password after calling Invoke-RestMethod, if needed.

Bash

curl {App URL}/Weatherforecast/RequireAuth \
   --cert ./sample.crt \
   --key ./sample.key \
   --insecure

Powershell

$parameters = @{
    Method  = 'GET'
    Uri     = '{App URL}/Weatherforecast/RequireAuth'
    Certificate  = (Get-PfxCertificate '.\sample.pfx')
}
Invoke-RestMethod @parameters

Self-signed certificate

Here is just my note of how to generate a self-signed certificate with openssl.

PEM DER PKCS#12
Data format Base64 ASCII Binary Binary
Extension .cer .pem .crt .key .cer .der .pfx .p12

Image description

Private key: sample.key
Public key: sample_public.key
Crtificate signing request: sample.csr
Certificate(PEM): sample.crt
Certificate(PKCS#12): sample.pfx

Create a private key

openssl genrsa -out sample.key 2048

Create a public key from the private key

openssl rsa -in sample.key -pubout -out sample_public.key

Create a CSR

openssl req -new -key sample.key -out sample.csr

Create a Certificate(PEM)

openssl x509 -signkey sample.key -in sample.csr -req -days 365 -out sample.crt

Create a Certificate(PKCS#12)

openssl pkcs12 -export -inkey sample.key -in sample.crt -out sample.pfx


This content originally appeared on DEV Community and was authored by Kohei Kawata


Print Share Comment Cite Upload Translate Updates
APA

Kohei Kawata | Sciencx (2022-04-18T10:54:11+00:00) Client certifiate authenticaiton of .NET 6.0 Web API. Retrieved from https://www.scien.cx/2022/04/18/client-certifiate-authenticaiton-of-net-6-0-web-api/

MLA
" » Client certifiate authenticaiton of .NET 6.0 Web API." Kohei Kawata | Sciencx - Monday April 18, 2022, https://www.scien.cx/2022/04/18/client-certifiate-authenticaiton-of-net-6-0-web-api/
HARVARD
Kohei Kawata | Sciencx Monday April 18, 2022 » Client certifiate authenticaiton of .NET 6.0 Web API., viewed ,<https://www.scien.cx/2022/04/18/client-certifiate-authenticaiton-of-net-6-0-web-api/>
VANCOUVER
Kohei Kawata | Sciencx - » Client certifiate authenticaiton of .NET 6.0 Web API. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/04/18/client-certifiate-authenticaiton-of-net-6-0-web-api/
CHICAGO
" » Client certifiate authenticaiton of .NET 6.0 Web API." Kohei Kawata | Sciencx - Accessed . https://www.scien.cx/2022/04/18/client-certifiate-authenticaiton-of-net-6-0-web-api/
IEEE
" » Client certifiate authenticaiton of .NET 6.0 Web API." Kohei Kawata | Sciencx [Online]. Available: https://www.scien.cx/2022/04/18/client-certifiate-authenticaiton-of-net-6-0-web-api/. [Accessed: ]
rf:citation
» Client certifiate authenticaiton of .NET 6.0 Web API | Kohei Kawata | Sciencx | https://www.scien.cx/2022/04/18/client-certifiate-authenticaiton-of-net-6-0-web-api/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.