8 min readMicrosoft Entra · App Registrations · Monitoring
What Microsoft does not tell you: expiring app credentials in Entra
Expiring app credentials in Microsoft Entra: what the portal, Entra recommendations, Message Center, Service Health and Key Vault actually report, what you can build yourself with PowerShell, Log Analytics or Logic Apps, and what that costs to run.
After the first outage from an expired client secret, every IT team asks the same question: could Microsoft not have warned us? The short answer: for app registrations there is no notification. The long answer is a map. Microsoft does offer several things, but each has a narrow job, and none is an alarm for your client secrets and certificates.
This post walks through the sources one by one, checked against Microsoft Learn. The basics, why credentials expire and how to rotate without downtime, are in Entra app registration secrets expire.
No e-mail for client secrets and certificates
Microsoft Learn documents no e-mail notification for expiring client secrets or certificates of an app registration. The only documented expiry e-mail concerns something else: for enterprise applications with SAML single sign-on, Entra ID sends a mail 60, 30 and 7 days before the SAML signing certificate expires, to up to five configured addresses. That is the certificate Entra uses to sign tokens, not the credential your application signs in with.
Microsoft's own advice in the Microsoft.Identity.Web documentation matches: check the "Expires" column under "Certificates & secrets" and use Entra recommendations. Both are views first, not alarms.
What the portal shows
Two places in the Entra admin center show expiry dates:
- The Certificates & secrets page of an app registration lists every client secret and certificate with its expiry date.
- The App registrations list has a "Certificates & secrets" status column. In my observation it shows "Current", "Expiring soon" or "Expired"; Microsoft does not document the thresholds behind those labels.
Both work as soon as somebody looks. For one tenant with ten apps a weekly glance is enough. For 40 customer tenants it means 40 sign-ins.
Microsoft Entra recommendations
Recommendations are the closest thing Microsoft has to a built-in expiry monitor. Four items concern app credentials, all currently in preview:
- Renew expiring application credentials (
applicationCredentialExpiry): credentials on an app registration that expire within the next 30 days. - Renew expiring service principal credentials (
servicePrincipalKeyExpiry): the same for credentials stored directly on the service principal. - Remove unused credentials from applications (
staleAppCreds). - Remove unused applications (
staleApps).
You find the list under Entra ID, Overview, tab Recommendations, or through Microsoft Graph at /beta/directory/recommendations. The admin center caps impacted resources at 50 entries; the full list is only available through Graph. Reports Reader is enough to read them. Microsoft names no specific licence for these four items; the overview only says some recommendations may need P2 or another licence and that preview requirements may change.
Three properties make this a dashboard item rather than an alert:
- Refresh: data is processed every 24 hours with a one-day lag, in rare cases up to 72 hours. A secret that expires tomorrow may still be missing today.
- Fixed threshold: 30 days, not configurable. Credentials that have already expired show as "completed", not as a problem.
- E-mail only for a new recommendation: in preview, Entra sends a mail when a recommendation is newly generated, to every user with an active Application Administrator assignment. Anyone who can only activate the role through PIM receives nothing; if nobody is actively assigned, no mail goes out. You cannot enter a recipient address, and Microsoft itself advises checking the recommendations regularly anyway.
Defender app governance (Workload ID Premium licence) adds filters by credential expiry date. That too is a view per tenant.
Message Center and Service Health
Neither channel in the Microsoft 365 admin center has anything to do with your credentials. Message Center announces planned changes to Microsoft services. Service Health reports incidents and advisories in the environment Microsoft operates; interruptions caused by changes in the customer-managed environment are explicitly not service incidents. An expired secret is exactly such a change.
Azure Key Vault warns, but only about itself
Key Vault is the one place where Microsoft does warn before expiry. Through Event Grid a vault emits the events Microsoft.KeyVault.SecretNearExpiry and Microsoft.KeyVault.CertificateNearExpiry, each 30 days before the expiry date, plus SecretExpired and CertificateExpired. Attach a Logic App or a Function and you have a real notification.
The limitation: this applies only to objects inside the vault. Store a client secret's value as a Key Vault secret with a hand-entered expiry date and Key Vault warns about that copy. The app registration knows nothing about the vault, and a secret created in the portal never shows up there.
What you can build yourself
Sign-in logs: the message after the outage
Once a secret has expired, Entra rejects the token request with AADSTS7000222 (InvalidClientSecretExpiredKeysProvided). The failure lands in the sign-in logs under service principal sign-ins. Stream the logs to Log Analytics through a diagnostic setting (Entra ID P1 or P2 required) and put an alert rule on top:
AADServicePrincipalSignInLogs
| where ResultType == "7000222"
| summarize Failures = count(), LastSeen = max(TimeGenerated)
by ServicePrincipalName, AppId, ServicePrincipalCredentialKeyId
This tells you quickly which app is down. Proactive it is not: the query fires only after the sign-in has already failed.
PowerShell with Microsoft Graph
Before expiry, only the expiry dates themselves help. Microsoft Graph exposes them through PasswordCredentials and KeyCredentials of every application, each with an EndDateTime. A runbook in Azure Automation with a managed identity, whose application permission Application.Read.All was granted once through admin consent, needs no secret of its own:
Connect-MgGraph -Identity # managed identity of the Automation account
$limit = (Get-Date).AddDays(30)
Get-MgApplication -All | ForEach-Object {
$app = $_
foreach ($cred in @($app.PasswordCredentials) + @($app.KeyCredentials)) {
if ($cred.EndDateTime -lt $limit) {
"$($app.DisplayName): $($cred.DisplayName) expires $($cred.EndDateTime)"
}
}
}
Microsoft publishes similar sample scripts with CSV export on Learn. You then send the output through a Logic App with the Office 365 Outlook action "Send an email (V2)".
Azure Automation or Logic Apps
The schedule is the easy part: Azure Automation runs the runbook daily, or a Logic App with a Recurrence trigger calls it and sends the mail. The first version takes an afternoon.
What self-built monitoring costs to run
The first version is not the problem. The third year is.
- The script needs a credential itself. A managed identity only works in its own tenant. For customer tenants you need a multi-tenant app registration with a certificate or secret, and that credential expires too. The monitor then fails on the same day as what it watches.
- Multi-tenant loops. Consent per tenant, a list of tenant IDs somebody maintains, error handling so one revoked consent does not abort the whole run, and mapping output to the right customer.
- Module upkeep. Graph PowerShell modules in Automation have to be pinned and occasionally rolled back; sign-in failures with managed identity after a module update are a known pattern.
- Alert fatigue. A daily mail with the same 30 lines gets filtered after two weeks. Thresholds, de-duplication, snooze and routing to the right customer contact are features nobody builds on day one.
- Ownership. The script belongs to the person who wrote it. When they leave, it keeps running until it does not.
Comparing the sources
| Source | Covers app registration credentials? | Proactive? | Multi-tenant? |
|---|---|---|---|
| Portal (Certificates & secrets, App registrations) | Yes | No, only when somebody looks | No, one sign-in per tenant |
| Entra recommendations | Yes, 30-day window | Partly, mail only for a new recommendation to active Application Administrators | No |
| SAML certificate mail (enterprise apps) | No | Yes (60, 30, 7 days) | No |
| Message Center, Service Health | No | No | No |
| Key Vault Event Grid | No, vault objects only | Yes (30 days) | No |
| Sign-in logs, Log Analytics | Yes | No, only after the failure | No, diagnostic setting per tenant |
| Own script, Automation, Logic App | Yes | Yes, with your own threshold | Yes, with your own effort |
| Monitoring service | Yes | Yes | Yes |
How SecretExpiry helps
SecretExpiry reads app registrations with the read-only Graph permission Application.Read.All and continuously syncs client secrets and certificates across many tenants. Alerts go out by e-mail per event or as a weekly digest, as a webhook to Microsoft Teams or Slack, and as a calendar subscription (ICS). Each tenant can have its own notification address, individual credentials can be snoozed, and the dashboard shows an urgent list. Setup is described in the docs; the service starts at 10 € per tenant per month, with a 14-day free trial.
What you can do this week
Whatever tool you pick: open the recommendations and the app registrations status column once in every tenant and note what expires within 30 days. Check whether anybody holds the Application Administrator role as an active assignment; otherwise even the recommendation mail never arrives. And decide who will still know where the script runs in three years.