Troubleshooting 8 min read Updated June 3, 2026

How to fix AADSTS7000222: “The provided client secret keys for app are expired”

If you are reading this, something just stopped working. A pipeline failed, an API started returning 401, a background job went silent, or a sign-in broke. And somewhere in the logs, you found this:

AADSTS7000222: The provided client secret keys for app '<your-app-id>' are expired.

The fix itself is quick. The harder part is why it happened at all. Azure knew this secret would expire, and it never told you. This guide covers the immediate fix, the reasons it can look like the fix did not work, and how to make sure you are never surprised by an expired secret again.

The 30-second fix: Go to Microsoft Entra admin center → App registrations → [your app] → Certificates & secrets, create a new client secret, copy its Value immediately, and paste it everywhere the old secret was used (app config, Key Vault, service connection, etc.). Then redeploy or restart. The rest of this article explains how to find everywhere it was used and how to stop this from recurring.

What AADSTS7000222 actually means

AADSTS7000222 is Microsoft Entra ID (formerly Azure AD) telling you that the client secret your application used to authenticate has passed its expiration date. The token request was rejected with invalid_client, because the credential it presented is no longer valid.

Two things are worth understanding up front:

  • The app registration itself did not expire. App registrations do not expire. Only their credentials — client secrets and certificates — have expiration dates. The registration is fine. Only the secret attached to it is dead.
  • There is no “renew” button. An expired secret cannot be extended or reactivated. You create a new secret, update every place the old one is referenced, and remove the old one. That is the entire fix.

This is different from AADSTS7000215: Invalid client secret provided, which usually means the secret value is wrong: a typo, a trailing space, the Secret ID pasted instead of the value, or the wrong tenant. If you are seeing 7000215, check that you copied the right value before you assume it expired.

How to fix it

1. Find the right app registration

Open the Microsoft Entra admin center and go to Identity → Applications → App registrations. Search for the app by name, or by the Application (client) ID shown in the error.

If you cannot find it under App registrations, look under Enterprise applications instead (more on that below).

2. Confirm the secret is expired

Open the app and go to Certificates & secrets → Client secrets. You will see each secret with an Expires date, and the expired one will be flagged. Note the Description and Secret ID of the expired secret, so you know which one expired and can match it to where it is used.

3. Create a new client secret

Click + New client secret, give it a clear description (for example, prod-api-2026, so you can recognize it later), and choose an expiry.

A few things to know about the expiry:

  • The Azure portal caps client secret expiry at 24 months. The “never expires” option was removed years ago, for security reasons.
  • Microsoft's own recommendation is 6 months for client secrets. Shorter is safer, but only if you have alerting in place to rotate them in time (see the prevention section).
  • You can create longer-lived secrets through the Azure CLI (az ad app credential reset) or Microsoft Graph, but that trades security for convenience, and is not recommended for production.

Click Add, then copy the Value immediately. This is the only time the secret value is ever shown. Once you navigate away, it is gone, and you have to create another one. This is also why a monitoring tool can never read your secret values: the Graph API does not return them after creation.

4. Update everywhere the secret is used

The new secret does nothing until the application actually uses it. The old, expired value is still sitting in one or more of these places:

  • App Service / Function App — Configuration → Application settings (often an AzureAd:ClientSecret or similar key). This one is commonly missed, because it is buried in the configuration blade.
  • Azure Key Vault — if your app pulls the secret from Key Vault, update the Key Vault secret's value, not the app config.
  • Azure DevOps / GitHub Actions service connections — classic service connections that authenticate with an app registration + secret will break the moment the secret expires. Update the service connection's credentials.
  • Logic Apps, Automation runbooks, Data Factory linked services — any of these that authenticate as the app registration.
  • Application config files, environment variables, container secrets, CI/CD variable groups — anywhere a developer hard-wired the value.
  • External / partner systems — if a third party authenticates as this app, they need the new value too.

Paste the new value, save, and redeploy or restart the affected service so it picks up the change.

5. Verify and clean up

Trigger the workflow that failed: re-run the pipeline, call the API, start the job again. Once it succeeds with the new secret, go back to Certificates & secrets and delete the expired secret, so it cannot cause confusion later.

Common reasons the fix looks like it did not work

“It still says expired even though I have an active secret”

Almost always, the application is still pointing at the old secret. An app registration can hold several secrets at the same time, and adding a new one does not change which one your app sends. Make sure the config, Key Vault, or service connection actually references the new value, then restart the service.

“The app isn't under App registrations — only Enterprise applications”

If the app shows up under Enterprise applications with an empty Owners list, and nothing appears under App registrations, the registration most likely lives in another tenant. This is common with third-party SaaS, marketplace apps, or apps created by someone who has since left the company. You cannot rotate a secret on a registration you do not own. You will need the owning tenant's admin, or the vendor, to issue a new credential.

“Unable to save — the credential limit has been reached”

If you cannot add a new secret, check the app's Supported account types. Apps set to personal Microsoft accounts and organizational are limited to two secrets. Delete an old or expired one to make room.

“I rotated it but the pipeline still fails”

For Azure DevOps in particular, the durable answer is not a new secret at all. Switch the service connection to Workload Identity Federation (OIDC), so it receives a short-lived token and never stores a secret that can expire. More on that below.

Find out which other secrets are about to expire

You just fixed one secret. How many others are close to expiring right now? Here is a Microsoft Graph PowerShell snippet that lists every client secret in your tenant, sorted by how soon it expires:

Connect-MgGraph -Scopes "Application.Read.All"

$apps = Get-MgApplication -All
$results = foreach ($app in $apps) {
    foreach ($secret in $app.PasswordCredentials) {
        [pscustomobject]@{
            AppName  = $app.DisplayName
            AppId    = $app.AppId
            KeyId    = $secret.KeyId
            Expires  = $secret.EndDateTime
            DaysLeft = [math]::Round(($secret.EndDateTime - (Get-Date)).TotalDays)
        }
    }
}

$results | Sort-Object DaysLeft | Format-Table

Swap PasswordCredentials for KeyCredentials to do the same for certificates. Run it, and you will almost certainly find a few secrets expiring in the next 30–60 days that nobody is watching.

That script is useful, but notice what it is not. It only tells you the truth at the moment you run it. To turn it into real protection, you would have to schedule it on an Automation account or a Logic App, wire up email or webhook delivery, handle authentication and permissions, format the output into something readable, and keep all of it working as your tenant grows. This is the fragile, hand-built monitoring that every team eventually reinvents.

The real problem: Azure never warned you

Here is the part worth pausing on. The Azure portal shows you every secret's expiration date. It simply does not tell you about it. There is:

  • no built-in expiration notification,
  • no centralized view across all your app registrations,
  • no alert into your email or incident channel.

So the first person to notice an expired secret is almost always a customer, or an engineer in the middle of an incident. The expiration date was visible the whole time. It was simply on a page that nobody had open.

In a small tenant, a scheduled PowerShell script may be enough. But a mid-sized Azure tenant easily runs 50 or more secrets across dozens of app registrations, each with its own expiration date. Tracking every one of them by hand, forever, is not a realistic operating model.

How to make sure this never surprises you again

Rotating the secret fixes this incident. Monitoring with alerts fixes the category of incident. With alerts in place, an expiration becomes a quiet calendar item instead of an outage.

A few things that matter to engineers specifically:

  • It never sees your secret values. Graph does not return secret values after creation, so there is nothing sensitive to store. Token Watch reads only metadata: names, key IDs, and expiration dates.
  • Read-only, always. It cannot modify your tenant, create credentials, or delete anything.
  • Setup takes about a minute. Sign in, grant the read-only consent, and you immediately see every expiration status across the tenant. No agents, scripts, or installations.
  • Alerts go where you already work: email, or a webhook into Slack, Teams, PagerDuty, ServiceNow, or whatever incident tool you already use.

The durable fix: stop using long-lived secrets at all

Monitoring solves the problem of being surprised. For new and high-value workloads, the deeper fix is to use credentials that do not expire on a manual schedule:

  • Managed identities — for Azure resources (App Service, Functions, VMs, and so on) calling other Azure or Microsoft services. Azure manages the credential lifecycle for you, so there is no secret to rotate.
  • Workload Identity Federation (OIDC) — for CI/CD (GitHub Actions, Azure DevOps) and external workloads. The platform exchanges a short-lived token, so there is no stored secret to expire.
  • Certificates — if you must use app-registration credentials, certificates are generally preferred over secrets, though they expire too and still need monitoring.

The honest reality is that most tenants cannot remove client secrets overnight. There are always legacy apps, third-party integrations, and edge cases that still need them. For everything you can migrate, migrate. For everything you cannot, monitor it, so an expiration never turns into an incident again.

FAQ

It means the client secret your application used to authenticate with Microsoft Entra ID has expired. The app registration is fine; only its secret credential is dead, and it can't be renewed — you create a new one.

Create a new client secret under your app registration's Certificates & secrets blade, copy the value immediately, update every place the old secret was referenced (app config, Key Vault, service connections, etc.), then redeploy or restart and delete the expired secret.

Azure shows expiration dates in the portal but has no built-in expiration alerting, no centralized cross-app view, and no webhook into your incident channel. You have to build monitoring yourself or use a tool that does it for you.

The Azure portal caps it at 24 months. Microsoft recommends 6 months. You can set longer via CLI or Graph, but it's not recommended for production.

7000222 specifically means the secret is expired. 7000215 means the secret is invalid — often a typo, a trailing space, the Secret ID pasted instead of the value, or the wrong tenant. Check your copied value before assuming expiration.

Run a Microsoft Graph PowerShell query against PasswordCredentials and KeyCredentials (script above), or use a monitoring service like Token Watch that surfaces every expiration date and alerts you before they lapse.

Back to all guides

Top