Fix Azure DevOps “AADSTS7000222: client secret expired”

Your Azure App Service deployment failed after a commit. Here’s the fast fix and the durable, secret‑less solution using Workload Identity Federation (OIDC).

Symptom: Azure Pipelines fails to deploy to Microsoft.Web/sites with invalid_client · AADSTS7000222.
Example (truncated):
Error: Failed to get resource ID for resource type 'Microsoft.Web/Sites' and resource name 'sample-website-dev'.
Error: Could not fetch access token for Azure. Status code: invalid_client ... AADSTS7000222: The provided client secret keys for app '***' are expired.
Visit: https://aka.ms/NewClientSecret

Why it happened

Classic Azure Resource Manager service connections that authenticate with an App Registration + client secret will break when that secret expires.

Azure DevOps then can’t exchange a token to call Azure APIs, so any task requiring ARM (for example, AzureRmWebAppDeployment@4) fails.

The durable fix: Stop using long‑lived secrets. Switch your service connection to Workload Identity Federation (OIDC) so the pipeline obtains a short‑lived token securely without storing a secret.

Long‑term, secure fix (create a new WIF service connection)

1. Azure DevOps → Project Settings → Service connections → New service connection.

2. Select Azure Resource Manager.

Azure DevOps Project Settings
Azure DevOps Project Service Connections
Azure DevOps new Workload Identity Federation service connection

3. For Identity type, pick App registration (automatic).

4. For Credential, choose Workload identity federation (OIDC).

5. Name it New Service Connection Workload Identity Federation (or your org’s convention) and grant access permission to all pipelines if needed.

Update your pipeline YAML

Edit azure-pipelines.yml and point your deployment task to the new service connection via azureSubscription:

azure-pipelines.yml - Azure App Service (Linux) deployment

task: AzureRmWebAppDeployment@4
  inputs:
    ConnectionType: 'AzureRM'
    azureSubscription: 'New Service Connection Workload Identity Federation'
    appType: 'webAppLinux'
    WebAppName: 'sample-website-dev'
    packageForLinux: '$(Build.ArtifactStagingDirectory)/**/*.zip'
    RuntimeStack: 'DOTNETCORE|8.0'

If you previously used a different task (e.g., AzureWebApp@1), the same principle applies - point the task’s subscription input to the new WIF service connection.

Theory in 60 seconds: why WIF is better

  • Secret‑less: no client secret to store, leak, or rotate.
  • Short‑lived tokens: each run exchanges an OIDC token for just‑in‑time access.
  • Least privilege: scope the service connection to a resource group and minimal roles.

Troubleshooting checklist

  • Ensure azureSubscription in YAML exactly matches the new connection name.
  • Confirm that your pipeline uses the updated YAML (clean caches, re‑queue).

References

↑ Top ↑