๐ Recipe ยท Entra ID & Identity
Find Entra ID App Registrations With Secrets or Certificates Expiring Soon
Audit all app registrations for client secrets and certificates nearing expiration so you can coordinate renewals before outages occur
Complexity
Intermediate
Impact
prevents-outage + security-hygiene + automation-friendly + scheduled-audit
Context
Why This Matters
Why this matters
Every Entra ID (Azure AD) application registration that integrates with APIs, SaaS apps, or custom workloads authenticates using either a client secret or a certificate (keyCredential). When those credentials expire, the app silently stops working โ causing broken integrations, failed automations, and production outages that are notoriously hard to diagnose after the fact.
Microsoft does not send proactive alerts for expiring app credentials by default. This recipe gives you a repeatable audit so you can find soon-to-expire secrets/certs across the entire tenant and coordinate renewals with the app owners in advance.
When to run it
- Weekly, as a scheduled housekeeping task
- Before scheduled change freezes or holidays
- After inheriting a new tenant or taking over IT responsibilities
- Whenever a production integration fails with an
AADSTS7000222orAADSTS700027error
Expected Outcomes
What you will have
- A complete list of app registrations with credentials expiring within a configurable window (default: 7 days)
- For each app: display name, appId, object id, credential type (secret vs. certificate), credential display name, and exact expiry timestamp
- Enough information to contact app owners and coordinate renewal before expiration
- An auditable record you can re-run on a schedule or commit to a runbook
Risks & Considerations
Warnings & gotchas
- Don't rotate credentials without the app owner. Replacing a secret/cert on the app registration breaks any workload still using the old credential. Always add the new one first, redeploy, then remove the old.
- Enterprise Applications โ App Registrations. This audit targets
/applications(app registrations). Service principals for gallery SaaS apps rarely carry secrets you manage โ focus on custom/line-of-business apps. - Federated credentials are not covered. Workload identity federation credentials (used by GitHub Actions, Kubernetes, etc.) don't expire the same way and use a different endpoint (
/applications/{id}/federatedIdentityCredentials). - Permission scope: Reading
passwordCredentialsandkeyCredentialsrequiresApplication.Read.Allat minimum. The secret value is never returned โ only the hint and metadata. - Pagination matters. Large tenants can have thousands of app registrations. Don't forget to follow
@odata.nextLinkor you will miss apps.
Required Permissions
| Permission | Why It's Needed |
|---|---|
| Application.Read.All | Required to list app registrations and read their passwordCredentials and keyCredentials metadata |
| Directory.Read.All | Useful for resolving app owners when coordinating renewals |
The fastest way to get this done: just ask Dex. Copy the prompt below and paste it into your Dex conversation.
For IT Admins
Paste into Dex Pro
Review expiring credentials in the Entra admin center
The portal doesn't have a single tenant-wide expiry report, so this is a per-app inspection workflow โ best for small tenants or spot checks. For scale, use the API or PowerShell approach.
- Sign in to the Microsoft Entra admin center as a Global Reader, Application Administrator, or higher.
- Navigate to .
- Select the All applications tab to include apps you don't own.
- Click the column selector and ensure Certificates & secrets visibility is enabled (or open each app individually).
- For each app of interest, open it and select .
- Review the Expires column under both Client secrets and Certificates tabs.
- Note any credential expiring within your renewal window (typically 7โ30 days).
- Click Owners in the left navigation to identify who to contact for renewal coordination.
Tip: The portal flags credentials expiring within 30 days with a yellow warning banner on the app's Overview page โ but you must visit each app to see it.
Query app credentials via Microsoft Graph
Use GET /applications and filter client-side on endDateTime. Graph does not support server-side $filter on passwordCredentials/endDateTime, so you must retrieve and evaluate.
Endpoint
GET https://graph.microsoft.com/v1.0/applications?$select=id,displayName,appId,passwordCredentials,keyCredentials&$top=999Required header
Authorization: Bearer {access_token}Sample response (trimmed)
{
"value": [
{
"id": "a1b2c3d4-...",
"appId": "9f8e7d6c-...",
"displayName": "Contoso Payroll Integration",
"passwordCredentials": [
{
"displayName": "prod-secret",
"endDateTime": "2025-02-14T10:00:00Z",
"keyId": "..."
}
],
"keyCredentials": []
}
],
"@odata.nextLink": "https://graph.microsoft.com/v1.0/applications?$skiptoken=..."
}Client-side filter logic
- Parse each app's
passwordCredentials[].endDateTimeandkeyCredentials[].endDateTime. - Keep only credentials where
endDateTimeis between now and now + N days. - Follow
@odata.nextLinkuntil absent โ do not stop at the first page.
Renewal workflow
To add a new secret before removing the old one:
POST /v1.0/applications/{id}/addPassword
Content-Type: application/json
{
"passwordCredential": {
"displayName": "renewed-2025",
"endDateTime": "2026-02-01T00:00:00Z"
}
}The response contains the secretText โ the only time the secret value is ever returned. Capture it securely and share with the app owner via an approved channel.
Audit with PowerShell + Microsoft Graph SDK
The Microsoft.Graph PowerShell module handles pagination automatically via -All and is the easiest way to produce a reusable report.
Prerequisites
- PowerShell 7+
Microsoft.Graphmodule:Install-Module Microsoft.Graph -Scope CurrentUser- Account with
Application.Read.Allconsent
One-liner preview
Connect-MgGraph -Scopes "Application.Read.All"
Get-MgApplication -All -Property Id,DisplayName,AppId,PasswordCredentials,KeyCredentials |
Where-Object {
($_.PasswordCredentials.EndDateTime -lt (Get-Date).AddDays(7)) -or
($_.KeyCredentials.EndDateTime -lt (Get-Date).AddDays(7))
} |
Select-Object DisplayName, AppIdThe full script below expands this with per-credential detail, CSV export, and configurable window.
Next steps