Most pipelines deploy with a long-lived credential: a client secret, an access key or an API token pasted into the CI/CD platform's secret store. That credential is effectively a password to production. It can leak through a compromised pipeline, a copied repository or a careless log line. It works from anywhere until someone revokes it. It expires at the worst possible time and breaks every deployment. And someone has to remember to rotate it.
OpenID Connect (OIDC), also called workload identity federation, removes the stored secret altogether. Instead of proving who it is with a password, the pipeline proves where it is running.
The CI/CD platform is the identity provider - for every run, it issues a signed token (a JWT) that describes the run, for example which repository, branch and environment it belongs to
The cloud trusts that issuer - you set up a federated credential (or trust policy) once, saying "accept tokens from this issuer, but only when the subject matches this repository and this environment"
The pipeline swaps the token - at run time, it exchanges the signed token for a short-lived cloud access token
The token expires - usually within minutes to an hour, and it is never stored anywhere
There is no password to store, leak, rotate or expire.
Nothing to steal - no credential is stored in the pipeline. A leaked pipeline file or repository copy gives an attacker nothing they can use elsewhere
Nothing to rotate - no expiry date to track, and no outage when a secret quietly expires
Short-lived - each token is valid for a single run
Scoped - the trust is limited to the repository, branch or environment you name, so a fork or another branch cannot use it
Auditable - cloud sign-in logs show exactly which repository and pipeline signed in
Pipeline secret: DEPLOY_CLIENT_SECRET - valid for 2 years, works from any machine, shared by every pipeline in the project
❌ Figure: Bad example - Bad example - A long-lived secret is a standing password to production
Federated credential: trust tokens from the CI/CD platform's issuer only when the subject is repo:YourOrg/YourRepo:environment:production - nothing is stored in the pipeline
✅ Figure: Good example - Good example - The cloud trusts one repository and environment, and each run gets a short-lived token
Scope the subject tightly - trust a protected environment or branch, not every branch or every repository in the organization
Protect the environment - require approvals and limit deployments to protected branches, so the trust only applies to reviewed code
Use least privilege - give the identity only the access the deployment needs, for example one resource group instead of the whole subscription
Use one identity per environment - production and test deployments should not share an identity
Remember the identifiers are not secrets - tenant, client or role IDs identify the identity, but they cannot be used to sign in on their own
Warning: The trust is only as tight as the subject you configure. A subject that is too broad (for example every branch, or a wildcard across repositories) lets any pipeline that can run there deploy to production.
Code that runs inside the cloud (for example an Azure App Service or Function) should use a managed identity at runtime, not a federated credential. See
Do you use Managed Identity in Azure?
Read the rule for your platform for the specific setup: