Skip to content
CAMPUX Cloud Bootcamp
Field notes · Identity & Access
App registration client secret alternatives

App registration client secret alternatives: the keyless options, ranked

By Captain O8 min read

A client secret is a password you paste into a config, forget to rotate, and eventually leak. Microsoft Entra gives you three ways off it — and which one you pick is decided entirely by where your workload runs.

New to cloud? CAMPUX is a free, build-first course. Start here →

Replace a client secret by matching the workload to the right credential: a managed identity if it runs inside Azure (no secret at all), workload identity federation if it runs outside Azure under a trusted identity provider like GitHub Actions (a short-lived token, no stored secret), and a certificate only when neither fits. In that order. Almost every "how do I avoid the client secret" question resolves the moment you answer "where does this code actually run?"

The client secret is the most common long-lived credential in an Azure estate, and it is the one that bites. It sits in an app setting or a pipeline variable, gets copied into a second service, shows up in a log, and quietly expires six months later and takes down a production integration on a Sunday. Entra has spent years building alternatives specifically so you never have to manage that string again. Here is the whole decision, top to bottom.

Why the secret is the problem, briefly

A client secret is a bearer credential: whoever holds the string is the app. That means it can be stolen from anywhere it is stored or transmitted, it has to be manually rotated before it expires, and its blast radius is however much access you granted the app. None of the alternatives below remove the app's permissions — you still scope those with RBAC and Graph consent — but they remove the secret, which is the part that leaks.

The decision rule: where does the workload run?

Where the code runsUseSecret to manage?
Inside Azure (VM, App Service, Function, Container Apps, AKS)Managed identityNone
Outside Azure, under a trusted IdP (GitHub, GitLab, other cloud, k8s)Workload identity federationNone
Neither (third-party SaaS, on-prem app that can't federate)Certificate credentialA cert — protect & rotate

Work down the table and stop at the first row that describes your workload. The rows are in order of preference for a reason: the first two eliminate the credential entirely, and the third at least replaces a weak credential with a strong one.

Option 1 — Managed identity (anything running in Azure)

If your code runs on an Azure resource, you almost never need an app registration with a secret at all. A managed identity is an identity Azure creates and manages for you; the platform hands your workload a token when it asks, and there is no credential you create, store, or rotate. Two flavours:

Turn one on and grant it a role — no secret anywhere in the flow:

# give an existing web app a system-assigned identity
az webapp identity assign --name "my-api" --resource-group "rg-app"

# grant that identity access to a resource (e.g. a Key Vault secret)
az role assignment create \
  --assignee "<identity-principal-id>" \
  --role "Key Vault Secrets User" \
  --scope "/subscriptions/<sub>/resourceGroups/rg-app/providers/Microsoft.KeyVault/vaults/my-vault"

In code you then request a token through the standard Azure Identity libraries with DefaultAzureCredential / ManagedIdentityCredential — the same call works locally (your own login) and in Azure (the managed identity), so there is no secret in either place.

Rule of thumb

If the answer to "where does this run?" is "on an Azure resource," you are done — reach for a managed identity and do not create a client secret in the first place. The other two options exist for code Azure is not hosting.

Option 2 — Workload identity federation (external callers)

When the caller runs outside Azure but under an identity provider Entra can trust — a CI/CD pipeline, another cloud, a Kubernetes service account — use workload identity federation. Instead of a secret, you register a federated credential on the app that says "trust a token from this issuer whose subject is exactly this." At run time the external system presents a short-lived OIDC token, Entra validates its issuer and subject against the credential, and issues an access token. Nothing long-lived is stored on either side.

The canonical case is GitHub Actions deploying to Azure — worth doing in full, because it is the single most common place a client secret leaks. We walk the entire setup, subject-claim gotchas included, in GitHub Actions OIDC to Azure: the passwordless setup. The federated-credential registration itself is one command:

az ad app federated-credential create --id "$appId" --parameters '{
  "name": "gha-main",
  "issuer": "https://token.actions.githubusercontent.com",
  "subject": "repo:my-org/my-repo:ref:refs/heads/main",
  "audiences": ["api://AzureADTokenExchange"]
}'

The same mechanism federates GitLab, other clouds, and Kubernetes workloads — only the issuer and subject change. If the caller can present a signed OIDC token, it can authenticate without a secret.

Option 3 — Certificate credential (last resort)

Sometimes neither fits: a third-party SaaS integration, or an on-prem service that cannot run in Azure and cannot present a federated token. Do not reach back for a client secret — add a certificate credential instead. A certificate is still a credential you must protect and rotate, but it is a real step up: it can live in a hardware module or a key vault, it is far harder to copy out of a log, and authentication proves possession without transmitting the secret itself.

# attach a certificate (public key) to the app registration
az ad app credential reset --id "$appId" \
  --cert "@mycert.pem" --append

Store the private key in Key Vault or the platform certificate store, never in source. The point of picking the certificate over a secret is that you are replacing a string anyone can copy with a key you can keep in hardware.

Migrating off a secret without downtime

An app registration can hold several credentials at once, so you never need a risky cutover. The safe order:

  1. Add the new credential alongside the secret — assign the managed identity, register the federated credential, or attach the certificate.
  2. Update the workload to use it, and confirm it authenticates in a real run.
  3. Only then delete the client secret from the app registration.

Because the old secret keeps working until you remove it, there is no gap. Do this per workload, verify each, and the secret is gone for good — not rotated, gone.

Rotating a secret is treating the symptom. Removing it is curing the disease.

Questions people also ask

What can I use instead of a client secret on an Entra app registration?

Three keyless options, chosen by where the workload runs. Inside Azure → a managed identity (no credential at all). Outside Azure under a trusted IdP like GitHub Actions → workload identity federation (a short-lived OIDC token). Only if neither fits → a certificate credential instead of a secret.

Is a managed identity better than a client secret?

Yes, for anything running in Azure. There is no secret you create, store, or rotate — the platform manages the credential and hands the workload a token on request, scoped by RBAC. Nothing to leak, nothing to expire.

What is workload identity federation?

It lets an external workload authenticate with a short-lived token from a trusted identity provider instead of a stored secret. You register a federated credential describing which external subject to trust; at run time the caller presents an OIDC token that Entra validates against it. No secret is stored.

When should I still use a certificate?

Only when neither a managed identity nor federation fits — a third-party or on-prem app that cannot do either. A certificate is still better than a secret because it can live in hardware or a vault and proves possession without sending the secret, but it is the last choice.

How do I migrate off a client secret without downtime?

Add the new credential alongside the old one, move the workload to it, confirm it works, then delete the secret. An app registration holds multiple credentials at once, so the old secret keeps working until you remove it — no cutover gap.

Further reading — the Microsoft docs
Your next class · free
You've read the idea. Class 1 — What is Cloud? is where you build it, hands-on — no account needed.Start Class 1 →
Captain O
Founder & instructor · CAMPUX Cloud Engineering Bootcamp
Related: GitHub Actions OIDC to Azure · What is Microsoft Entra ID? · Azure MFA best practices · 100 Days of Azure →