Find expiring app secrets and certificates before they bite
Expired client secrets cause some of the most avoidable outages in Entra. A short Graph script shows what's about to expire across the tenant.
On this page
App registrations authenticate with client secrets or certificates, and both expire. When one does, an integration quietly stops working, often on a Monday morning. Entra doesn't email the app owner by default, so you need your own early warning.
Client secret
- A password for the app
- Expires and must be rotated
- Easily copied into scripts
Certificate
- Private key stays on the host
- Still expires
- Harder to leak by accident
Managed identity / federation
- No credential to store
- No expiry to manage
- The preferred option where possible
The script
This lists every secret and certificate on every app registration, with the days remaining, sorted so the most urgent are first:
Connect-MgGraph -Scopes "Application.Read.All"
$days = 60
$now = Get-Date
Get-MgApplication -All -Property DisplayName,AppId,PasswordCredentials,KeyCredentials |
ForEach-Object {
$app = $_
$creds = @(
$app.PasswordCredentials | ForEach-Object { [pscustomobject]@{ Type="Secret"; Name=$_.DisplayName; End=$_.EndDateTime } }
$app.KeyCredentials | ForEach-Object { [pscustomobject]@{ Type="Certificate"; Name=$_.DisplayName; End=$_.EndDateTime } }
)
foreach ($c in $creds) {
[pscustomobject]@{
App = $app.DisplayName
AppId = $app.AppId
Type = $c.Type
Name = $c.Name
Expires = $c.End
DaysLeft = [int]($c.End - $now).TotalDays
}
}
} |
Where-Object DaysLeft -le $days |
Sort-Object DaysLeft |
Format-Table -AutoSizeNegative DaysLeft values are already expired. Those are worth a look too: an expired secret that nobody noticed might mean the app is no longer used and can be cleaned up.
Making it useful
- Export it. Swap
Format-TableforExport-Csvand share it with app owners. - Run it on a schedule. An Azure Automation runbook with a managed identity granted
Application.Read.Allcan run it weekly and email the results. - Set owners. Every app registration should have at least two owners, so there's always someone to chase.
- Prefer certificates or managed identities. Shorter secret lifetimes are safer, but managed identities remove the problem entirely for Azure-hosted workloads.
Running it weekly with Azure Automation
- Create an Automation account with a system-assigned managed identity.
- Grant the identity the Microsoft Graph application permission
Application.Read.All. - Add the Microsoft.Graph.Authentication and Microsoft.Graph.Applications modules to the account.
- Create a PowerShell runbook with the script, replacing
Connect-MgGraph -Scopes …withConnect-MgGraph -Identity. - Schedule it weekly and send the results to a shared mailbox or Teams channel.
What to do with the list
- Expiring soon: contact the owner and agree a rotation date.
- Already expired: check whether the app is still used before renewing; it may be safe to delete.
- No owner: find one before the next expiry, or plan to retire the app.
This post was last checked against Microsoft's documentation over six months ago. The approach should still hold, but check the linked sources for anything that has changed before you act on it.
Next in Automating Entra and Azure safely · part 5 of 5Six KQL queries for Entra sign-in logs every admin should keep →