Why this is a problem in the first place
App Registrations authenticate with client secrets or certificates, and both have an expiry date
— secrets typically 3 to 24 months out, certificates on whatever lifetime you issued them
with. When one expires, nothing warns the app beforehand. It just starts failing, usually surfaced by
AADSTS7000222 in logs.
Entra doesn't proactively email you about this by default. The closest it comes is a recommendation you have to go looking for, gated behind a role and, on some tenants, a license. Everything past that is on you to build or buy.
Three ways to catch it, compared
Each option trades setup time against long-term ownership. None of them are wrong — they just fit different tenants.
| DIY script | Entra native recommendation | Token Watch | |
|---|---|---|---|
| Setup time | Hours to days | Minutes, once you find it | Minutes |
| Who maintains it | You, indefinitely | Microsoft | Token Watch |
| Alert channels | Email, if you build the delivery yourself | None — dashboard only | Email, Slack, Teams, webhooks — plus an Azure DevOps work-item integration |
| License required | None beyond Graph read access | May require Entra P1/P2 | None — standard Graph read access |
| Warning threshold | Whatever you code | Fixed at ~30 days | Configurable |
| Notification strategy | Whatever you code | Fixed, one-time | Repeat until resolved, or only on status change |
| Recipients | Whoever you hardcode | Application Administrator role only |
Any number, plus per-app owners on paid plans |
| Collaboration | One script, one owner | Role-gated | Built-in RBAC — multiple people can contribute |
| Ignore a specific credential? | Only if you build a suppression list | No | Yes — mark it untracked |
| Cost | Your time, indefinitely | Included in P1/P2 | Free tier; paid plans for full alerting |
Method 1: a PowerShell script on a schedule
Call Microsoft Graph — Get-MgApplication, expanding keyCredentials
and passwordCredentials — list every secret and certificate, check the expiry
dates, and email the results. Run it from Task Scheduler, an Azure Automation runbook, or a Logic
App.
It costs nothing but time, and you already have the Graph access to do it. The catch is that the
script becomes a piece of infrastructure you now own. Real, commonly reported failure modes: the
Graph SDK module updates and a cmdlet's output shape changes under you; Connect-MgGraph
works fine interactively but the auth pattern that relies on doesn't survive unattended in a runbook;
and if the schedule itself silently stops firing, you get no report and nothing tells you that you
got no report.
Setup also takes longer than it looks. Even starting from a script that already works, wiring up unattended auth, testing the schedule, and getting delivery actually firing end to end takes a few hours at minimum — copy-pasting a gist rarely gets you there in one sitting.
- Email only, unless you build Slack, Teams, or webhook delivery on top yourself.
- No concept of app ownership — the script tells you a secret is expiring, not who to page about it.
- Runs only when triggered. A failed schedule looks identical to a tenant with nothing expiring.
- No granularity. There's no way to mute a single credential you don't care about — you can build a suppression list, but now that's one more thing you maintain.
- Every new requirement is a code change. Notifying app owners instead of just yourself, adding a channel, changing how often it repeats — each one means editing the script and testing it again, not flipping a setting.
- Reports live in an inbox or a file share. A CSV or an HTML email is awkward to hand to the rest of the team to divide up or track against.
Best fit: a single Entra admin who already lives in PowerShell, doesn't need Slack or Teams delivery, and is willing to own the maintenance for as long as the script runs.
Method 2: Entra's native recommendation
Entra ID's Identity Secure Score includes a Renew expiring application credentials
recommendation, currently preview, that flags apps with a credential expiring inside roughly the
next 30 days. It's built into the admin center, so there's nothing to install, and it can trigger a
preview email — but only to whoever holds the Application Administrator role, not
the app's actual owner, and only once, when the recommendation first appears.
Even where it works, it's a dashboard you have to remember to check, not a push notification: fixed 30-day window, not configurable, and multiple practitioners report it showing nothing even when expiring credentials clearly exist in the tenant. The full breakdown of what this recommendation does and doesn't cover goes deeper into the role gating and the data-freshness gaps.
Best fit: tenants already on P1/P2 who are disciplined about checking a dashboard weekly and don't need push alerts to Slack or Teams.
Method 3: Token Watch
Token Watch connects to your tenant with read-only Microsoft Graph access, syncs your App Registrations on a schedule, and alerts you — by email, Slack, Teams, or a signed webhook — when a tracked secret or certificate is expired or inside your configured warning window.
The trade you're making is the opposite of the DIY script: no maintenance burden, but you're granting a third party consent to read your tenant. What that access is scoped to: read-only Graph permissions, and Token Watch never reads or stores the secret values themselves — only names, IDs, and expiry dates. There's a free tier if you want to see your own tenant's exposure before deciding on anything more.
What it gets you that a script or the native recommendation can't, without you having to build any of it:
- Alerts to more than one inbox — tenant-wide recipients, plus notifications to each application's own owner on paid plans, instead of everything landing on one admin.
- A choice of notification strategy: keep getting reminded until a credential is actually rotated, or only get notified when its status changes.
- Delivery to email, Slack, Microsoft Teams, or a signed webhook into your own pipeline.
- An Azure DevOps integration that goes beyond a notification: it creates a work item per expiring credential and tracks it against that secret, so rotation becomes something the team pulls into a sprint instead of an email someone has to remember.
- Built-in RBAC, so more than one person can share monitoring duty instead of it depending on whoever wrote the script or holds the role.
- An inventory of every credential in one screen, so you can mark the irrelevant ones untracked instead of drowning in noise.
- A configurable warning threshold instead of a fixed 30 days.
- No dependency on an Entra P1/P2 license — standard Graph read access is enough.
Which one should you actually use?
- One admin, comfortable owning a script, email is enough. The DIY route works — just budget real maintenance time for it, not zero.
- Already on P1/P2, disciplined about checking a dashboard. The native recommendation costs nothing extra. Just know it won't come looking for you — you still have to go looking for it.
- You want this solved and forgotten, or want alerts somewhere other than email. That's what Token Watch is for — setup is minutes, not the few hours a DIY script needs even when you're starting from one that already works, and it removes both the maintenance burden and the license gate. It's built specifically to solve this one problem instead of doing it as a side effect of something else.
Whichever you pick, the goal is the same: find out from an alert, not from
AADSTS7000222 in your error
logs after something already broke.
Written by Maksym Vostruhin
Founder of Token Watch. Built it after chasing down one too many expired App Registration secrets by hand across a growing set of Entra tenants.
FAQ
Renew expiring application credentials recommendation, which is preview,
dashboard-first, and only emails the Application Administrator role once
when it first appears.
Token Watch