From Client Secrets to Certificate-Based Authentication: Building a Secure Integration with Azure Key Vault and Azure Functions for a US based AI & Cyber Security Company - CloudFronts

From Client Secrets to Certificate-Based Authentication: Building a Secure Integration with Azure Key Vault and Azure Functions for a US based AI & Cyber Security Company

Summary

Enterprise API integrations require more than simply obtaining an access token. The authentication model must provide a reliable way for an application to establish its identity while protecting the credentials used to do so.

In this implementation, we explored a certificate-based authentication architecture using Microsoft Entra ID, an X.509 self-signed certificate, Azure Key Vault, Azure Functions, Managed Identity, and Microsoft Authentication Library (MSAL).

The objective was to replace dependency on an expiring client secret with a certificate-backed application identity, while keeping the private certificate protected within Azure infrastructure.

This article walks through the complete implementation — from creating the certificate and registering its public key, to storing the private certificate in Key Vault, configuring the Function App, and ultimately obtaining an OAuth 2.0 access token through MSAL.

Case Study

Read more about our Journey with this Customer over here: View Case Study

Introduction

Enterprise applications increasingly depend on APIs to connect business processes across platforms. Microsoft Partner Center and other Microsoft services provide powerful APIs for automation, reporting, partner operations, customer processes, and broader Microsoft ecosystem integrations.

As an integration moves toward production, however, authentication becomes an architectural concern rather than simply a configuration task.

A client secret may be sufficient during initial development, but production integrations introduce additional questions:

  • How should application credentials be protected?
  • How should credentials be rotated?
  • How can private credentials be kept outside application code?
  • How can authentication be centralized for multiple consumers?
  • How can the solution reduce dependency on manually managed secrets?

These considerations led to a certificate-based authentication approach:

Use a certificate-backed application identity, protect the private certificate in Azure Key Vault, and use an Azure Function with Managed Identity and MSAL to obtain the downstream access token.

The implementation described in this article demonstrates that architecture from beginning to end using a self-signed certificate as the initial certificate credential.

The Business Requirement

The requirement was to establish an application-to-application authentication mechanism for Microsoft API integrations without relying on a long-lived client secret embedded across application components.

The traditional client-secret model is straightforward:

Application
     ↓
Client ID + Client Secret
     ↓
Microsoft Entra ID
     ↓
Access Token
     ↓
Target API

The challenge is that the client secret behaves like a password. It must be securely stored, rotated, replaced before expiration, and carefully distributed to every application or service that needs it.

The target architecture instead establishes application identity using a certificate:

Application
     ↓
Certificate-backed application identity
     ↓
Microsoft Entra ID
     ↓
Access Token
     ↓
Target API

Azure Key Vault then provides the security boundary for the private certificate material.

Why Certificate-Based Authentication?

Certificate authentication is based on asymmetric cryptography. The certificate contains a public key and corresponds to a private key.

The public certificate can be registered with Microsoft Entra ID, while the private key remains protected by the application infrastructure.

                    Microsoft Entra ID
                          │
                   Public Certificate
                          │
                          │ validates
                          ▼
Azure Function ────── Signed Assertion
       │
       │
       └── Private Key
             protected by
             Azure Key Vault

The important difference from a client secret is that the application proves possession of the private key rather than sending a reusable password-like credential as its application credential.

Microsoft Authentication Library (MSAL) supports certificate credentials for confidential client applications. In MSAL.NET, the .WithCertificate() configuration allows MSAL to use the certificate to perform the client authentication process.

Solution Overview


Certificate based authentication architecture
End-to-end certificate-based authentication architecture

The implementation separates authentication responsibilities across several Azure and Microsoft identity components.

Component Responsibility
Microsoft Entra App Registration Represents the application identity
Public Certificate Registered with Entra ID to validate the application
Private Certificate Used to prove possession of the registered certificate
Azure Key Vault Protects the private certificate material
Managed Identity Allows the Function App to access Key Vault without another secret
Azure Function Centralizes token acquisition
MSAL Handles the OAuth 2.0 client-credential authentication process
Access Token Used to authorize requests against the target API

The Authentication Architecture

The complete authentication sequence can be simplified to:

1. Application calls the authentication Function
                    ↓
2. Function authenticates to Azure Key Vault
   using Managed Identity
                    ↓
3. Function retrieves the private certificate
                    ↓
4. MSAL loads the certificate
                    ↓
5. MSAL creates the signed client assertion
                    ↓
6. Assertion is sent to Microsoft Entra ID
                    ↓
7. Entra validates the certificate
                    ↓
8. Entra issues the access token
                    ↓
9. Function returns the access token
                    ↓
10. Consumer uses the token against the target API
The key architectural separation is that the consumer does not need to manage the private certificate directly. The authentication layer manages certificate access and token acquisition.

Step 1 — Creating the Microsoft Entra App Registration

The first step is to create an App Registration representing the application that will authenticate with Microsoft Entra ID.

For this implementation, the test application registration was:

skenycerttestappreg

The App Registration provides the application’s Client ID and Tenant ID and acts as the identity against which the certificate credential is registered.

The App Registration stores the public certificate credential. It does not require the private key to be uploaded to Entra ID.

Step 2 — Creating the Self-Signed Certificate

For the initial implementation, a self-signed certificate was created locally using PowerShell.

$cert = New-SelfSignedCertificate `
    -Subject "CN=Test App Registration Certificate" `
    -CertStoreLocation "Cert:\CurrentUser\My" `
    -KeyExportPolicy Exportable `
    -KeySpec Signature `
    -KeyLength 2048 `
    -NotAfter (Get-Date).AddYears(2)

This creates a certificate containing both the public and private portions. The certificate is stored in the Windows certificate store under the current user’s Personal certificate store.


Launching Certificate Manager
Launching Certificate Manager using Win + R → certmgr.msc


Certificate Manager
Locating the newly created certificate under Personal → Certificates

The certificate now provides the cryptographic identity that will be associated with the App Registration.

Step 3 — Exporting the Certificate

Two certificate representations are required for this implementation.

File Purpose
.cer Public certificate uploaded to Microsoft Entra ID
.pfx Certificate containing the private key, imported into Azure Key Vault

Exporting the public certificate

First, the public certificate is exported without its private key. This certificate can safely be uploaded to the App Registration.


Starting Certificate Export Wizard
Right-click → All Tasks → Export to start the Certificate Export Wizard


Certificate Export Wizard
Certificate Export Wizard — welcome screen


Export without private key
Selecting “No” to export the certificate without the private key


DER encoded certificate
Selecting DER encoded binary X.509 (.CER)


Saving certificate
Saving the exported .cer file


Certificate export path
Confirming the .cer file path


Completing public certificate export
Completing the export — Export Keys: No

Exporting the private certificate

The same certificate is then exported again, this time including its private key. The resulting PFX file will be protected in Azure Key Vault.


Export private key
Selecting “Yes” to include the private key


PFX export format
Selecting Personal Information Exchange (.PFX)


Protecting PFX private key
Password-protecting the exported private key


Saving PFX
Saving the .pfx file


PFX file path
Confirming the .pfx file path


Completing PFX export
Completing the export — Export Keys: Yes


Certificate thumbprint
Verifying the certificate thumbprint

The thumbprint is important because it identifies the certificate that represents the application’s cryptographic identity. The public certificate registered with Entra and the private certificate used by the Function must correspond to the same certificate.

Step 4 — Importing the Private Certificate into Azure Key Vault

The PFX contains the private key and therefore becomes the sensitive part of the authentication architecture.

Instead of storing the PFX directly inside the Function App or application configuration, it was imported into Azure Key Vault.

In this implementation, the Key Vault was:

skenycerttestkeyvault

The certificate was imported using the PFX file created in the previous step.


Azure Key Vault certificate import
Azure Key Vault — creating a certificate using the Import method


Certificate imported into Key Vault
Certificate successfully imported into Azure Key Vault

The certificate can now be accessed by an authorized Azure workload without requiring the private certificate to be embedded in application code.

Azure Function
      ↓
Managed Identity
      ↓
Azure Key Vault
      ↓
Private Certificate

Step 5 — Registering the Public Certificate with Entra ID

The public .cer file is uploaded to the App Registration under Certificates & secrets → Certificates.


App Registration certificate upload
Uploading the public .cer certificate to the App Registration


Certificate registered with Entra
Certificate successfully registered with the App Registration

At this point, Microsoft Entra ID knows which public certificate should be associated with the application.

App Registration
       ↕
Public Certificate
 
Private Certificate
       ↓
Azure Key Vault

The private key remains outside the App Registration.

Step 6 — Creating the Azure Function

The next component is an Azure Function App running .NET 8 isolated.

The Function exposes an HTTP-triggered endpoint:

/api/GetToken

Azure Function App overview
Azure Function App used as the token acquisition layer

Its responsibility is deliberately narrow:

Retrieve the certificate securely, authenticate the application with Microsoft Entra ID using MSAL, and obtain the requested access token.

This creates a centralized authentication layer that can be consumed by downstream business applications without distributing the private certificate across those applications.

Step 7 — Enabling Managed Identity

The Function App is configured with a System-assigned Managed Identity.


Function App managed identity
Enabling the System-assigned Managed Identity

This gives the Function App its own Azure identity. That identity is then used to authenticate to Key Vault.

Azure Function
      │
      │ Managed Identity
      ▼
Azure Key Vault

This is an important part of the design because the Function does not need another client secret simply to access the certificate stored in Key Vault.

Step 8 — Granting Key Vault Access

The Function’s Managed Identity must be granted permission to access the certificate in Key Vault.

For this implementation, the appropriate built-in Key Vault role was assigned to the Function’s Managed Identity.


Key Vault role assignment
Selecting the appropriate Key Vault built-in role


Assigning Function Managed Identity
Assigning the Function App’s Managed Identity


Key Vault IAM
Verifying the role assignment at the Key Vault IAM scope

The Function Managed Identity and the App Registration are two different identities serving two different purposes. Managed Identity provides access to Azure resources such as Key Vault, while the App Registration represents the application identity used with Microsoft Entra ID.

Step 9 — Configuring Function App Settings

The Function requires configuration values describing the application identity, Key Vault location, certificate name, and target API scope.


Function App environment variables
Function App configuration for Tenant ID, Client ID, Key Vault, certificate, and scope

The configuration follows the pattern:

Setting Purpose
TENANT_ID Microsoft Entra tenant containing the App Registration
CLIENT_ID Application / Client ID of the App Registration
KEY_VAULT_URL Azure Key Vault endpoint
CERTIFICATE_NAME Name of the certificate stored in Key Vault
SCOPE Target API resource scope used during token acquisition

Keeping these values in application configuration rather than hard-coding them makes the Function easier to deploy across environments.

Step 10 — Implementing Certificate Authentication with MSAL

The Azure Function brings together the Managed Identity, Azure Key Vault, the certificate containing the private key, and MSAL.NET to obtain an access token from Microsoft Entra ID.

Function Authentication Flow

1. Start the Azure Function
 
2. Read the required configuration:
   - Tenant ID
   - Client ID
   - Key Vault URL
   - Certificate Name
   - Target API Scope
 
3. Authenticate to Azure Key Vault
   using the Function App's Managed Identity
 
4. Retrieve the certificate from Key Vault
   including its private key
 
5. Load the certificate into an
   X509Certificate2 object
 
6. Create an MSAL Confidential Client
   using the Entra App Registration
   Client ID and Tenant ID
 
7. Associate the retrieved certificate
   with the MSAL Confidential Client
 
8. Request an application access token
   for the configured API scope
 
9. MSAL authenticates the application
   with Microsoft Entra ID using the certificate
 
10. Microsoft Entra ID validates the
    certificate-based application identity
 
11. Receive the access token
 
12. Return the access token to the caller

What Happens Behind the Scenes

The Function does not directly authenticate to the target Microsoft API. Instead, it first establishes the application’s identity with Microsoft Entra ID using the certificate registered against the App Registration.

The private key remains protected in Azure Key Vault. The Function retrieves the certificate through its Managed Identity and provides it to MSAL. MSAL then performs the certificate-based client authentication and requests an access token for the configured resource.

The key separation is:

Managed Identity → allows the Function to securely access the certificate in Key Vault.

Certificate → proves the identity of the Entra App Registration.

MSAL → uses the certificate to authenticate the application and obtain the access token.

Final Result

Once Microsoft Entra ID successfully authenticates the application, the Function receives the access token. This token can then be used as a bearer token when calling the configured downstream Microsoft API.

With .WithCertificate(), MSAL handles the certificate-based client authentication process. The application does not need to manually create or persist the client assertion.

Step 11 — Obtaining the Access Token

Once the Function is configured, the authentication endpoint can be called to initiate the complete flow.

HTTP Request
     ↓
Azure Function
     ↓
Managed Identity
     ↓
Azure Key Vault
     ↓
Private Certificate
     ↓
MSAL
     ↓
Microsoft Entra ID
     ↓
Access Token

The Function endpoint used during testing was:

/api/GetToken

The Function successfully returned an access token.


Postman GetToken access token
Calling the GetToken Function and receiving the access token

At this point, the certificate-based authentication chain has completed successfully.

Certificate → Key Vault → Managed Identity → MSAL → Microsoft Entra ID → Access Token

Understanding the Client Assertion

One concept that can initially be confusing is the relationship between the certificate, client assertion, and access token.

They are three different components of the authentication process.

Certificate
    ↓
Signed Client Assertion
    ↓
Microsoft Entra ID
    ↓
Access Token
    ↓
Target API

The certificate is the long-lived cryptographic credential. The client assertion is a short-lived signed authentication artifact used during token acquisition.

The access token is then issued by Microsoft Entra ID and is the credential presented to the target API.

The client assertion is not something that needs to be generated manually and stored for the lifetime of the certificate. MSAL generates and signs the assertion as part of the token acquisition process when .WithCertificate() is used.

This distinction is important when designing certificate-based authentication:

Component Purpose
Certificate Application credential and cryptographic identity
Client Assertion Short-lived proof generated during authentication
Access Token Credential used to access the target API

Security and Production Considerations

The implementation demonstrates the authentication pattern, while a production deployment should apply additional security controls around the infrastructure.

Protect the private certificate

  • Do not store PFX files in source control.
  • Do not embed private keys in application code.
  • Use Azure Key Vault for protected certificate storage.
  • Use least-privilege access for the Function Managed Identity.

Protect the authentication endpoint

During development and controlled testing, the Function can use a Function-level authorization key.

For production, the token acquisition endpoint should itself be protected and only accessible to authorized workloads.

Business Application
        ↓
Protected Authentication Endpoint
        ↓
Azure Function
        ↓
Managed Identity
        ↓
Key Vault
        ↓
Certificate
        ↓
MSAL
        ↓
Microsoft Entra ID
        ↓
Access Token

Plan certificate lifecycle

  • Monitor certificate expiration.
  • Define renewal procedures.
  • Plan certificate rotation.
  • Maintain the relationship between the registered public certificate and private certificate.

The self-signed certificate used in this implementation is appropriate for demonstrating and validating the authentication architecture. Production environments should evaluate the organization’s certificate policy and appropriate certificate authority requirements.

Protect tokens

Access tokens should also be treated as sensitive credentials. They should not be written to application logs, source control, browser storage, or other locations where unnecessary exposure could occur.

Key Implementation Lessons

Lesson 1: A certificate is not an access token

The certificate establishes the application’s identity. Microsoft Entra ID uses that identity to issue an access token for the requested resource.

Lesson 2: The public and private certificate have different responsibilities

The .cer file can be registered with Microsoft Entra ID because it contains the public certificate. The .pfx contains the private key and therefore requires protected storage.

Lesson 3: Key Vault protects the long-lived credential

The private certificate is considerably more important to protect than a short-lived authentication artifact. Key Vault provides a dedicated security boundary for that credential.

Lesson 4: Managed Identity removes another static credential

The Function can authenticate to Key Vault using its Managed Identity, avoiding the need to introduce another client secret simply to retrieve the certificate.

Lesson 5: MSAL handles the authentication mechanics

Using .WithCertificate() allows MSAL to manage the certificate authentication and client assertion process instead of requiring custom JWT assertion generation.

Lesson 6: Centralized authentication can simplify the application landscape

Rather than distributing certificate credentials across multiple plugins, flows, applications, and scripts, a centralized authentication service can provide a controlled token acquisition layer.

Frequently Asked Questions

1. Why use a certificate instead of a client secret?

A client secret is a password-like credential that requires secure storage and rotation. A certificate provides an asymmetric credential model where the private key can be protected separately from the public certificate registered with Microsoft Entra ID.

2. Why were both .cer and .pfx files created?

The .cer contains the public certificate and is registered with Entra ID. The .pfx contains the certificate together with its private key and is used by the authentication service.

3. Does the private key need to be uploaded to Entra ID?

No. The public certificate is registered with the App Registration. The private key remains protected by the application infrastructure.

4. Why use Azure Key Vault?

Key Vault provides a dedicated location for protecting the private certificate rather than placing the PFX directly inside application code or source control.

5. Why does the Function need Managed Identity?

Managed Identity allows the Function to authenticate to Azure resources such as Key Vault without requiring another client secret.

6. Does MSAL generate the client assertion?

Yes. When .WithCertificate() is used, MSAL handles the certificate-based client authentication process.

7. Do we need to store the client assertion?

No. The assertion is part of the token acquisition process and is not a long-term credential that should be stored.

8. What is the final output of the authentication flow?

The final output is an OAuth 2.0 access token issued by Microsoft Entra ID. That token can then be presented to the target API according to the permissions and scope configured for the application.

9. Can this pattern be used for Microsoft Partner Center?

Yes. The same certificate-based confidential-client pattern can be used when the target API supports Microsoft Entra application authentication, with the appropriate Partner Center resource, permissions, and scope configured for the application.

10. Can the same architecture support other Microsoft APIs?

The authentication architecture can be reused for other Microsoft APIs where application authentication through Microsoft Entra ID is supported. The target API’s required permissions and scope must still be configured independently.

Conclusion

Certificate-based authentication is more than a replacement for a client secret. It provides an opportunity to rethink how application identity, private credentials, and token acquisition are managed across an enterprise integration.

In this implementation, the authentication chain was deliberately separated into distinct responsibilities:

Microsoft Entra ID
→ Application identity
 
Public Certificate
→ Registered application credential
 
Private Certificate
→ Cryptographic proof
 
Azure Key Vault
→ Private certificate protection
 
Managed Identity
→ Azure resource authentication
 
Azure Function
→ Centralized token acquisition
 
MSAL
→ Certificate-based client authentication
 
Access Token
→ Authorization to the target API

Starting with a self-signed certificate provided a practical way to validate the architecture end-to-end. The implementation demonstrated the complete journey from certificate creation to secure storage, application registration, Function configuration, MSAL authentication, and successful access-token acquisition.

More importantly, the architecture establishes a foundation that can evolve beyond a single integration. Certificate lifecycle management, stronger endpoint protection, controlled access to Key Vault, and centralized token acquisition can all be incorporated as the solution moves from development toward production.

Key Takeaway:

The question should not simply be, “Where should we store the client secret?” The better architectural question is, “How can we establish application identity while protecting long-lived credentials and minimizing their distribution?”

The combination of Microsoft Entra ID, certificate authentication, Azure Key Vault, Managed Identity, Azure Functions, and MSAL provides a strong foundation for building that model.


Share Story :

SEARCH BLOGS :

FOLLOW CLOUDFRONTS BLOG :


Categories

Secured By miniOrange