Skip to main content
AppAlert

Azure DevOps service connection secret expired

Reviewed

On this page
Credential type
Client Secret
Resource type
Application
Blast radius
Every pipeline that uses the Azure Resource Manager service connection, until the secret is renewed or the connection is converted
Likely first responder
Pipeline owners, when a deployment task fails to get a token
Suggested owner
Azure DevOps service connection administrator, with an Entra app owner or Application Administrator for the secret
Suggested planning buffer
30 calendar days

What breaks

When a pipeline fails with AADSTS7000222, the client secret on the app registration behind its Azure Resource Manager service connection has expired. The service connection signs in to Entra with that secret. Once the secret expires, Entra rejects the sign-in, and every pipeline task that uses the connection fails. Microsoft's troubleshooting guide for Azure Resource Manager service connections lists three messages for this case:

  • AADSTS7000222: The provided client secret keys for app '***' are expired
  • AADSTS7000215: Invalid client secret is provided
  • Invalid client id or client secret

The Entra error code reference names AADSTS7000222 InvalidClientSecretExpiredKeysProvided and describes it as "The provided client secret keys are expired."

Every pipeline and stage that references the connection fails, in every run, until someone renews the secret or converts the connection. Deployments stop. Nothing changes in the Azure resources they target. For expired client secrets in general, see Client secret expired.

Catch the secret before your pipeline fails

AppAlert emails your admins before the app secret behind a service connection expires. Read-only, free during Early Access. Connect read-only

Read-only permissions
Microsoft Graph application permissions Application.Read.All, Directory.Read.All, AgentIdentity.Read.All, AgentIdentityBlueprint.Read.All, AgentIdentityBlueprintPrincipal.Read.All, plus User.Read for sign-in. No write permissions: AppAlert cannot create, rotate, or delete credentials.
Never received
Secret values, certificate private keys, Microsoft account passwords, and mailbox contents. AppAlert stores credential metadata such as type, expiry date, and owner email addresses.
Where data lives
App functions and database in Frankfurt, Germany (Vercel fra1, Neon on AWS eu-central-1). Alert emails are sent through Resend, which stores them in the United States. Data location
Revoke any time
A Microsoft Entra administrator can revoke AppAlert's enterprise application consent. That stops future directory reads; deleting stored data is a separate request. Retention and revocation

How you notice

The first sign is usually a failed pipeline run with one of the messages above. In Azure DevOps, open Project settings, then Service connections, then the connection. The 2024 Sprint 236 release notes say the service connection details page shows when its secret has expired.

Rule out look-alikes before you renew anything. The troubleshooting guide says to check whether the connection is enabled before you troubleshoot authentication or rotate secrets. These failures look similar but need different fixes:

  • Connection disabled. A service connection administrator or Project Administrator can disable it, and Azure Pipelines might disable it after 100 days without use. Check the Usage history tab and the Azure DevOps Audit log, then select Enable.
  • AADSTS700016, application not found. The service principal was deleted. Create a new connection, or for a manual connection, enter new service principal details.
  • AADSTS7000112, application is disabled. The "Enabled for users to sign-in" option is off on the enterprise application linked to the service principal.
  • AuthorizationFailed. The service principal is missing an Azure role on the scope named in the error.
  • "Resource not authorized". The pipeline has no permission to use the service connection.

To check expiry dates ahead of time, list the Azure Resource Manager connections that use a service principal in a project with the Azure CLI. The commands need the Azure CLI with the azure-devops extension (az extension add --name azure-devops) and a sign-in with az login, and the PowerShell part needs the Microsoft Graph PowerShell module (Microsoft.Graph.Applications). Set the two variables first:

ORG="https://dev.azure.com/your-organization"
PROJECT="Your project"
az devops service-endpoint list --org "$ORG" --project "$PROJECT" \
  --query "[?(type=='azurerm' || type=='AzureRM') && authorization.scheme=='ServicePrincipal'].{name:name, mode:data.creationMode, appId:authorization.parameters.serviceprincipalid, tenantId:authorization.parameters.tenantid}" -o table

The mode column shows Automatic if Azure DevOps created the connection and Manual if a person did. The appId column is the application (client) ID. The tenantId column is the Microsoft Entra directory ID of the app registration. The type and scheme filter follows Microsoft's conversion script on the connect to Azure page, which requests type=azurerm and authSchemes=ServicePrincipal. The page on automating service connections says serviceprincipalid holds the app's appId. The ServicePrincipal scheme also covers connections that authenticate with a certificate instead of a secret. If an app has no passwordCredentials in the next step, it likely uses a certificate, so check its keyCredentials instead.

Then use the appId and tenantId from the table to read the secret expiry dates for each app registration with Microsoft Graph PowerShell:

$appId = "00000000-0000-0000-0000-000000000000"
$tenantId = "00000000-0000-0000-0000-000000000000"
Connect-MgGraph -TenantId $tenantId -Scopes Application.Read.All
Get-MgApplication -Filter "appId eq '$appId'" -Property displayName,appId,passwordCredentials |
  Select-Object -ExpandProperty PasswordCredentials |
  Select-Object DisplayName, KeyId, EndDateTime

Why it happens

Secrets expire. The troubleshooting guide says the service principals and secrets that Azure DevOps creates automatically "expire and require renewal." Rotate secret renews the secret "for three more months," so an automatic connection that stays on a secret needs a renewal about four times a year.

Microsoft treats the secret option as legacy. The connect to Azure page lists "Automatic app registration with a secret" among the options that exist "for backwards compatibility and edge cases and not recommended." The page on alternate approaches warns that a secret "requires manual rotation and management."

Ownership is split. Microsoft says that "Azure DevOps service connection permissions don't grant permission to update identities in Azure or Microsoft Entra," and that the app registration "might be owned by a different user or team." The person who sees the failed pipeline often cannot fix the secret, and the person who can works in another team.

Nobody watches the date. A pipeline that deploys rarely may not fail until weeks after the secret expired.

Renewal path

  1. Confirm the connection is enabled and the error is one of the three expired-secret messages. If not, work through the look-alikes in How you notice.
  2. Find out whether the connection is automatic or manual. Use the mode column from the CLI command above. The connection's Overview tab also shows its creator and authentication type, as described in Manage service connections.
  3. For an automatic connection, the preferred fix is to convert it to workload identity federation, if your policy and tasks allow it. Go to Project settings, then Service connections, select the connection, and select Convert. A connection with an expired secret shows "a different option to convert." The conversion tool works only if Azure DevOps created the connection and only one project uses it. You can revert within seven days. On the connect to Azure page, Microsoft lists Marketplace extension tasks that support workload identity federation as a prerequisite for federated app registrations, so check the tasks your pipelines use. For AADSTS7000215, the conversion troubleshooting table says to convert the connection and replace the expired secret with federated credentials.
  4. If you cannot convert today, renew the secret on the automatic connection. Go to Project settings, then Service connections, select the connection, and select Rotate secret. If Rotate secret is not shown, select Edit, then Save. The troubleshooting guide says the renewed secret lasts three more months and that you can rotate before it expires. The user needs "proper permissions on the subscription and Microsoft Entra ID," because the action updates the secret on the app registration.
  5. For a manual connection, renew the secret in Entra and update the connection.
    1. In Entra, open the app registration, then Certificates & secrets, then New client secret, and choose a duration. Copy the value right away, because Entra shows it only once. See Manually set an Azure Resource Manager service connection with a secret and Microsoft's credential guide.
    2. An owner of the app registration, or a user with the Application Administrator or Cloud Application Administrator role, can add the secret. Both roles are in the supported roles list for addPassword.
    3. In Azure DevOps, edit the service connection, enter the new value, and save. On Microsoft's setup page for manual connections, the field is Client secret and the button is Verify and save. Then run the pipeline.
    4. Keep the old secret until the pipeline has run on the new one. Check which credential the workload still uses to confirm the key ID in the service principal sign-in logs, then delete the old secret.
  6. Plan the move off secrets for a manual connection too. Add a federated credential on the app registration with the Issuer and Subject identifier values that Azure DevOps shows, then switch the connection to workload identity federation, as described in Set up workload identity federation manually. New federated connections use the Microsoft Entra issuer, and the older Azure DevOps issuer retires on July 1, 2027.

Who should own it

Two roles in two systems have to work together. In Azure DevOps, the Administrator role on a service connection "can use the service connection and manage roles for other users and groups." The user who creates the connection gets that role automatically, and the project's Endpoint Administrators group has it by default, according to Set service connection security. That role does not grant permission to update identities in Entra.

In Entra, give the app registration at least two owners from the team that runs the pipelines, or agree on a contact in the identity team who holds Application Administrator or Cloud Application Administrator.

If you do not know who owns the app registration, the troubleshooting guide says to check the app registration owners in Entra. If you cannot identify one, contact the directory or subscription administrator. If the owner list is empty, see Entra app credential expired with no owner. If the person who created the connection has left the organization, check who else holds the Administrator role on it.

Lead time and business-day math

Suggested planning buffer: 30 calendar days, the same as the other Catalog entries.

On an automatic connection, the renewal itself takes minutes. The lead time is for finding one person who has the Administrator role on the connection plus the Entra and subscription rights, or for getting both teams into the same change. On a secret that lasts three months, a 30-day buffer means planning starts about two months after the last rotation.

Converting to workload identity federation takes longer to schedule than a rotation, because extension tasks must support it and the change may need approval. Start it well before the next expiry. Subtract weekends, holidays, approval time, and deployment freezes when scheduling either change.

For client secrets in general, see Client secret expired.

A manual connection that uses a certificate instead of a secret follows Client authentication certificate expired.

For an app registration with no owner, see Entra app credential expired with no owner.

If the app registration still lists an owner who has left the organization, see Entra app credential expired after the owner left.

"Old Entra app credential removed too early" is planned as a separate entry.

Monitored by AppAlert

Monitored

AppAlert tracks the expiry of client secrets on every app registration in the connected directory. That includes the app registration behind a secret-based service connection, whether Azure DevOps or a person created it. Azure DevOps creates that app registration in the Entra directory of the selected subscription. If that is not the directory connected to AppAlert, AppAlert does not see it.

AppAlert does not read Azure DevOps. It cannot tell which service connection or pipeline uses a secret, and it does not rotate secrets or convert connections. It does not read federated credentials. To match an entry to a connection, search Applications in AppAlert by the client ID that the service connection shows, then act on the credential in the Operations queue. After you rotate or replace the secret, the new expiry appears after AppAlert syncs again. Set the warning days for client secrets in notification thresholds, and see coverage for what AppAlert reads.