Jump to Section
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.
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
azureSubscriptionin YAML exactly matches the new connection name. - Confirm that your pipeline uses the updated YAML (clean caches, re‑queue).
References
- Microsoft Docs - Set a workload identity service connection (Azure DevOps): https://learn.microsoft.com/en-us/azure/devops/pipelines/release/configure-workload-identity?view=azure-devops
- Microsoft Docs - Use an Azure Resource Manager service connection (convert to WIF): https://learn.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure?view=azure-devops
- Microsoft Docs - Workload identity federation concepts (Entra ID): https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation
- Task reference - AzureRmWebAppDeployment@4: https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/reference/azure-rm-web-app-deployment-v4?view=azure-pipelines
- Error background - AADSTS7000222 (client secret expired): https://login.microsoftonline.com/error?code=7000222 and https://aka.ms/NewClientSecret