Skip to content
CAMPUX
Field notes · Identity
Managed identity vs service principal

Managed identity vs service principal: stop putting secrets in your app

By 14 min read

They are the same kind of identity underneath — but one hands you a password to guard, and the other never does. Here is the honest difference, when to reach for each, and why the interview answer is almost always "managed identity."

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

Here is a scene that has leaked more Azure credentials than any hacker: an app needs to read a storage account, so someone pastes a connection string into a config file, the config file goes into Git, and eight months later that string is still valid and still in the history. The whole reason both service principals and managed identities exist is to end that scene. They are two answers to the same question — how does a piece of software prove who it is to Azure? — and the difference between them is entirely about who holds the keys.

Both are the same thing underneath

In Microsoft Entra ID, a human logs in as a user principal. An application logs in as a service principal — the security object that says "this app is allowed to do these things in this tenant." You grant it roles, it gets tokens, it accesses resources. That is the identity every non-human workload uses.

So where does managed identity fit? This is the sentence that makes the whole topic click: a managed identity is a special type of service principal that Azure creates and manages for you. Microsoft's own documentation lists "managed identity" as one of the three kinds of service principal. It is not a different species of thing. It is a service principal whose credentials you are never given, never see, and never have to rotate — because the platform does all of that on your behalf.

That single distinction — do you hold a credential, or does Azure? — is the entire decision.

A service principal needs a stored secret; a managed identity has Azure issue a token — nothing to store.Service principalyour appclient secretyou store it & rotate ita secret that can leakManaged identityyour appon Azurea token, issuedby Azure · short-livedno secret to store
Figure — Both let an app authenticate to Azure, but a service principal needs a client secret you store, protect, and rotate — and that secret can leak. A managed identity has Azure issue a short-lived token to the app automatically, so there is no secret in your code or config at all. Prefer a managed identity wherever the workload runs on Azure.

The service principal: an identity with a password you own

When you register an application in Entra ID, you get an application object (the global blueprint) and a service principal (the local instance in your tenant that actually gets permissions). To let that app authenticate, you add a credential: a client secret or a certificate. Now your app can present its client ID plus that secret, get a token, and go.

The catch is right there in the last sentence. You created that secret, so you have to store it somewhere the app can read it, keep it out of source control, and rotate it before it expires. Every one of those is a place where things go wrong. A client secret is a password — and passwords in config files are exactly the leak we started with.

Service principals are still the right tool when there is no Azure resource to attach an identity to — most classically, code running outside Azure: a script on someone's laptop, an on-premises server, or historically a CI runner. They also back multi-tenant applications, where the same app object gets a service principal in every customer's tenant.

The managed identity: an identity with no password anyone holds

A managed identity is what you use when your code runs on an Azure resource — a Virtual Machine, App Service, Function, Container App, or an AKS pod through workload identity. You flip it on, and Azure quietly creates a service principal for that resource and manages its credentials invisibly. Your code asks the local Azure identity SDK for a token, the platform hands one over, and there is never a secret in your config, your Key Vault, or your Git history — because there is no secret to put anywhere.

Managed identities come in two flavours, and knowing the difference is a common interview follow-up:

The tell in an interview

If someone asks "how does your app authenticate to Key Vault?" and the answer contains the word secret, there is usually a better answer. "A system-assigned managed identity with the Key Vault Secrets User role" says you understand that the strongest credential is the one that does not exist.

So which do you use?

The rule is short: if your code runs on an Azure resource that supports managed identity, use a managed identity. No secret to leak, nothing to rotate, nothing to accidentally commit. You only fall back to a service principal with its own secret or certificate when nothing Azure-hosted is there to carry the identity for you — and even then, the modern move is to avoid the secret entirely.

That last point is worth naming, because it dissolves the most common "but I have to use a service principal" case: GitHub Actions deploying to Azure. You do not store a client secret for that anymore. You federate the pipeline to Azure with OpenID Connect, so the workflow trades a short-lived GitHub token for an Azure token at run time. Same identity model, zero stored secrets — a running gh secret list that returns nothing is the goal.

The strongest credential is the one that does not exist to be stolen.

Getting off a client secret: the keyless options, ranked

If you already have an app registration with a client secret in it, the question is not really "managed identity or service principal" — it is "what replaces this string?" A client secret is a bearer credential: whoever holds it is the app. It can be stolen from anywhere it is stored or transmitted, it has to be rotated manually before it expires, and its blast radius is however much access you granted. None of the alternatives below change the app's permissions, which you still scope with RBAC and consent. They remove the part that leaks.

The whole decision resolves the moment you answer one question: where does this code actually run?

Pick by where the workload runs — stop at the first row that describes it
Where the code runsUseSecret to manage?
Inside Azure (VM, App Service, Functions, Container Apps, AKS)Managed identityNone
Outside Azure, under a trusted identity provider (GitHub, GitLab, another cloud, Kubernetes)Workload identity federationNone
Neither (third-party SaaS, on-premises app that cannot federate)Certificate credentialA certificate — protect and rotate

The rows are in preference order for a reason: the first two eliminate the credential entirely, and the third at least replaces a weak credential with a strong one.

Workload identity federation, for callers outside Azure

When the caller runs outside Azure but under an identity provider Entra can trust — a deployment pipeline, another cloud, a Kubernetes service account — 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 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 a CI/CD pipeline deploying to Azure, which is the single most common place a client secret leaks. The 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 other clouds and Kubernetes workloads; only the issuer and subject change. If the caller can present a signed token, it can authenticate without a secret. The full setup, subject-claim traps included, is in pipelines without secrets.

A certificate, only as a last resort

Sometimes neither fits: a third-party integration, or an on-premises service that cannot run in Azure and cannot present a federated token. Do not reach back for a client secret — attach a certificate credential instead. A certificate is still something 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. Store the private key in Key Vault or the platform certificate store, never in source.

Migrating off a secret without downtime

An app registration can hold several credentials at once, so you never need a risky cutover. Add the new credential alongside the secret — assign the managed identity, register the federated credential, or attach the certificate. Update the workload to use it and confirm it authenticates in a real run. 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 rather than rotated.

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

The mental model to keep

Picture a building. A service principal is a contractor with a physical key card you cut, handed over, and now have to remember to deactivate when they leave. A managed identity is an employee whose badge the building's own security desk issues, rotates, and revokes automatically — you just say who they are and what floors they can reach. Both open doors. Only one leaves a key card in a drawer for someone else to find.

Get comfortable saying that out loud, assign roles to the identity rather than sprinkling secrets around, and you have removed an entire category of breach from your architecture before you have written a line of application code.

Questions people also ask

What is the difference between managed identity and service principal?

They are not really different categories. A service principal is the identity object every non-human workload uses in Entra ID. A managed identity is one kind of service principal, created and rotated by Azure itself. The real difference is who holds the credential: you hold it for a plain service principal, Azure holds it for a managed identity.

Is a managed identity a type of service principal?

Yes. Microsoft's documentation lists managed identity as one of three kinds of service principal in Entra ID. It behaves like any other service principal, you grant it roles and it gets tokens, except Azure creates its credential, stores it, and rotates it, so no client secret or certificate ever exists for you to protect.

Can a managed identity be used outside Azure?

No. A managed identity only exists because Azure attaches it to a resource it manages, a VM, App Service, Function, or AKS pod. Code running outside Azure, like a laptop script, an on-premises server, or a legacy CI runner without federation, has no resource for Azure to attach an identity to, so it needs a service principal instead.

What is the difference between system-assigned and user-assigned managed identity?

A system-assigned identity is created on one resource and shares its lifecycle, delete the VM, and Azure deletes the identity with it; it cannot be shared. A user-assigned identity is a standalone resource you attach to one or many others, with its own lifecycle. Microsoft recommends user-assigned as the default, since permissions can exist before the compute does.

When should you use a service principal instead of a managed identity?

Use a service principal when there is no Azure resource to hang a managed identity on: code outside Azure, multi-tenant apps that need a service principal per customer tenant, or legacy pipelines. For GitHub Actions deploying to Azure, skip stored secrets entirely and federate with OpenID Connect instead of creating a plain service principal secret.

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, which has no credential at all. Outside Azure under a trusted identity provider such as a CI/CD pipeline, workload identity federation, which exchanges a short-lived token. Only if neither fits, a certificate credential instead of a secret. Add the new credential alongside the old secret, verify it, then delete the secret.

Further reading — the Microsoft docs
Your next class · free
You've read the idea. Class 9 — Service Principals & Managed Identity is where you build it, hands-on — no account needed.Start Class 9 →
Captain O
Founder & instructor · CAMPUX Cloud Engineering Bootcamp
LinkedIn
Drilled in Class 9 — Service Principals & Managed Identity. Next note: Private endpoints, explained without the fog →