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.
Table of Contents
- Introduction
- The Business Requirement
- Why Certificate-Based Authentication?
- Solution Overview
- The Authentication Architecture
- Step 1 — Creating the Microsoft Entra App Registration
- Step 2 — Creating the Self-Signed Certificate
- Step 3 — Exporting the Certificate
- Step 4 — Importing the Private Certificate into Azure Key Vault
- Step 5 — Registering the Public Certificate with Entra ID
- Step 6 — Creating the Azure Function
- Step 7 — Enabling Managed Identity
- Step 8 — Granting Key Vault Access
- Step 9 — Configuring Function App Settings
- Step 10 — Implementing Certificate Authentication with MSAL
- Step 11 — Obtaining the Access Token
- Understanding the Client Assertion
- Security and Production Considerations
- Key Implementation Lessons
- Frequently Asked Questions
- Conclusion
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:
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
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
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:
The App Registration provides the application’s Client ID and Tenant ID and acts as the identity against which the certificate credential is registered.
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.
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.
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.
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:
The certificate was imported using the PFX file created in the previous step.
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.
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:
Its responsibility is deliberately narrow:
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.
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.
Step 9 — Configuring Function App Settings
The Function requires configuration values describing the application identity, Key Vault location, certificate name, and target API 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.
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.
.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:
The Function successfully returned an access token.
At this point, the certificate-based authentication chain has completed successfully.
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.
.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.
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.
