Back to Blog
Azure
7 min read

Stop Using Client Secrets for API Auth: The Certificate-Based OAuth Flow Your Third Parties Need

AzureAPI ManagementOAuthSecurityAuthentication

A third party needs access to your APIs. The default instinct — on both sides — is to generate a client secret in an Entra ID app registration, hand it over, and move on. It works. It is fast to implement. And it creates a maintenance burden that nobody thinks about until the secret expires and production breaks.

We recently designed an API authentication solution for a third-party integration sitting behind Azure API Management and Application Gateway. The journey through the available options is worth documenting because the "obvious" choices kept getting ruled out by architectural constraints.

The Architecture

The API landscape was not simple. Requests from the third party would traverse:

  1. Azure Application Gateway with WAF — TLS termination and web application firewall
  2. Azure API Management — Policy enforcement, rate limiting, request validation
  3. Backend APIs — The actual services behind APIM

Each layer has its own authentication and security considerations, and the interactions between layers constrain which authentication methods are viable.

Why Client Secrets Are Problematic

Client secrets are the most commonly used credential type for OAuth 2.0 client credentials flow, and they work fine for internal service-to-service communication where you control both sides. For third-party integrations, they introduce operational friction:

Rotation overhead. Secrets expire. When they do, someone needs to generate a new one, securely transmit it to the third party, and coordinate the cutover. Miss the expiry date and the integration breaks. Set a long expiry to avoid the hassle and you have a long-lived credential floating around.

Shared secret exposure. Both parties know the secret. You cannot distinguish between legitimate use by the third party and use by someone who obtained the secret through a breach on their side. There is no way to audit which specific key pair or certificate was used — it is the same secret value every time.

No asymmetric trust. The third party can do anything the secret allows. If they store it insecurely, if a developer puts it in a Git commit, if it ends up in a log file — your APIs are exposed until you rotate it.

Options We Evaluated

Client Certificates (mTLS)

Mutual TLS is the gold standard for API authentication. The third party presents a client certificate during the TLS handshake, and the server validates it against a trusted CA or certificate thumbprint. No shared secrets, strong authentication, full audit trail.

Why it did not work here: Application Gateway terminates TLS. The client certificate presented by the third party is consumed by Application Gateway and not forwarded to APIM. You can configure Application Gateway to pass the certificate in a header, but APIM would need custom policy to extract and validate it, and the certificate validation happens at a different layer than the authentication decision.

This is a common architectural constraint. If your API stack has a TLS-terminating reverse proxy in front of the service that needs to validate the certificate, mTLS becomes significantly more complex.

Managed Identity

Azure Managed Identity is the cleanest authentication method for Azure-to-Azure communication. No credentials to manage, automatic token rotation, tight RBAC integration.

Why it did not work here: The third party's application does not run on Azure. Managed Identity requires the calling application to be hosted on Azure infrastructure (a VM, App Service, Function App, etc.) so it can obtain tokens from the Azure Instance Metadata Service. Cross-tenant managed identity is technically possible but adds significant complexity, and it still requires the caller to be on Azure.

APIM Subscription Keys

API Management subscription keys are simple, effective, and built into the platform. You create a subscription, hand over the key, and APIM validates it on every request.

Why it was our fallback, not our primary: Subscription keys are effectively long-lived API keys with no expiry by default. They have the same shared-secret problems as client secrets, just at a different layer. For lower-security scenarios or internal APIs, they are perfectly adequate. For a third-party integration where security posture matters, we wanted something stronger.

The Winner: Certificate-Based Client Credentials

The solution was OAuth 2.0 client credentials flow using certificates instead of secrets. Here is how it works:

  1. You create an app registration in Entra ID for the third-party integration
  2. The third party generates a certificate (a key pair — public and private)
  3. They send you the public certificate (the .cer file, not the private key)
  4. You upload the public certificate to the app registration under Certificates & Secrets → Certificates
  5. The third party uses their private key to sign a JWT assertion
  6. They exchange the signed assertion for an access token at the Entra ID token endpoint
  7. They present the access token to your APIs in the Authorization header
  8. APIM validates the token using standard JWT validation policies

The critical difference from client secrets: you never hold the private credential. The third party generates their own key pair, keeps the private key, and gives you only the public half. If they need to rotate, they generate a new key pair, send you the new public certificate, and you upload it. At no point do you handle, transmit, or store a secret.

Token Request with Certificate

The third party's token request looks like this (pseudo-code):

POST https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token

client_id={app-registration-client-id}
&scope=api://{your-api-app-id}/.default
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion={signed-jwt}
&grant_type=client_credentials

The client_assertion is a JWT signed with their private key. Entra ID validates the signature against the public certificate you uploaded. If it matches, a short-lived access token is returned. The token typically has a 60-90 minute lifetime, so even if it is intercepted, the exposure window is narrow.

APIM Validation Policy

On the APIM side, validate the incoming token with a standard policy:

<validate-jwt header-name="Authorization" failed-validation-httpcode="401">
    <openid-config url="https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration" />
    <required-claims>
        <claim name="aud" match="all">
            <value>api://{your-api-app-id}</value>
        </claim>
    </required-claims>
</validate-jwt>

This validates the token signature, expiry, audience, and issuer without any custom code.

Why This Shifts the Operational Burden

The operational elegance of this approach is in who manages what:

ResponsibilityClient Secret ModelCertificate Model
Generate credentialYouThird party
Store private credentialBoth partiesThird party only
Rotate credentialBoth parties coordinateThird party rotates, sends new public cert
Exposure riskBoth partiesThird party only
Token lifetimeN/A (secret is long-lived)60-90 minutes

Certificate renewal becomes the third party's responsibility. They generate a new key pair, send you the new public certificate, and you upload it alongside the existing one (Entra ID supports multiple certificates on a single app registration for zero-downtime rotation). You remove the old certificate after the transition period.

Compare this to secret rotation, where you generate a new secret, securely transmit it (how?), coordinate a cutover window, verify the third party has updated their configuration, and then revoke the old secret. The coordination overhead alone makes certificate-based auth worth it.

When to Use What

MethodBest ForAvoid When
Certificate-based OAuthThird-party integrations, high-security APIsInternal service-to-service (overkill)
Client secret OAuthInternal services, prototyping, low-risk APIsThird-party access, production APIs
Managed IdentityAzure-hosted service-to-serviceCross-cloud, on-premises callers
APIM subscription keysInternal APIs, developer portalsExternal third-party production access
mTLSDirect service-to-service without TLS terminationArchitectures with reverse proxies that terminate TLS

The right choice depends on your architecture, your threat model, and who manages the credential lifecycle. For third-party integrations behind APIM, certificate-based client credentials hit the sweet spot of strong security with minimal operational overhead on your side.


Designing API authentication for your Azure environment? Our free assessment includes a review of your authentication patterns and security posture alongside cost analysis.

Need help with your Azure environment?

Get in touch for a free consultation.

Get in Touch