If you have ever received a call on a Monday morning saying “the integration stopped working” and after an hour of troubleshooting you found out that the client secret of an Entra ID app registration expired over the weekend, then this post is for you. Or maybe it was the SAML certificate of an Enterprise App, and suddenly nobody can sign in to Salesforce. Same pain, different blade.

In this post, I’ll show you how to set up Entra ID app secret expiry notifications that go straight to the people who own each app. A free PowerShell runbook in Azure Automation checks every app registration and every SAML Enterprise App in Microsoft Entra ID (formerly Azure AD), finds the client secrets and certificates that are about to expire, and emails each owner a clean HTML report of exactly what to renew

Get the Script

You can download the PowerShell Runbook from my GitHub repo

Prerequisites

  • An Azure Automation Account (PowerShell 5.1 or 7.x runtime).
  • An Entra ID app registration for the runbook, with these Application permissions and admin consent:
    • Application.Read.All (Microsoft Graph): reads app registrations, Enterprise Apps, their credentials, and their owners.
    • User.Read.All (Microsoft Graph): reads the owners’ email addresses. Without it, every report goes to the fallback mailbox.
    • Mail.Send: assign it through Exchange Online RBAC for Applications, scoped to the sender mailbox only, and don’t also grant it in Entra ID.
  • A certificate: the public key (.cer) uploaded to the app registration, and the .pfx uploaded to the Automation Account as AppMonCert.
  • Three Microsoft Graph modules imported into the Automation Account: Microsoft.Graph.Authentication (first), Microsoft.Graph.Applications, and Microsoft.Graph.Users.Actions.
  • A shared mailbox to send the emails from (no license needed).

Required Automation Variables and Certificate

The runbook has no parameters. It reads everything from the Automation Account, so create these under Shared Resources with the names exactly as shown. All of them are required, and the job stops with a clear error naming any one that is missing.

NameTypeExample valuePurpose
AAtenantVariable (String)00000000-0000-0000-0000-000000000000Your Entra ID tenant ID
AppReg_AppIDVariable (String)11111111-1111-1111-1111-111111111111Application (client) ID of the runbook’s app registration
AppMonSenderMailboxVariable (String)noreply@contoso.comMailbox the emails are sent from
AppMonFallbackEmailVariable (String)it-team@contoso.comReceives reports for apps with no owner
AppReg_DaysThresholdVariable (Integer)30How many days ahead to look; expired credentials are always included
App_Reg_IncludeAdminVariable (String)admin1@contoso.com,admin2@contoso.comAdmins who receive the full tenant report, comma separated

How the Entra ID App Secret Expiry Runbook Works

  1. Reads its settings from the Automation Variables and the AppMonCert certificate.
  2. Connects to Microsoft Graph with certificate authentication.
  3. Checks every app registration’s client secrets and certificates against the threshold.
  4. Checks every Enterprise App configured for SAML SSO, looking only at the active signing certificate.
  5. Finds the owners of each app. Apps without a reachable owner go to the fallback mailbox (SAML apps try their notification email first).
  6. Groups the results by owner, so each person gets one email listing only their apps.
  7. Sends the full tenant report to the admins, then disconnects from Graph.

Here is a screenshot of what the application owner receives

Here is a screenshot of what the admin receives

How It work

The runbook reads owners with Get-MgApplicationOwner for app registrations and Get-MgServicePrincipalOwner for SAML apps, and keeps only owners it can email:

  • Service principals are skipped, since they have no mailbox.
  • Users without a mail address are skipped, with a warning in the job output naming their object ID.
  • Guest users with a mail address are included, so they receive the report at their external address. Remove guests as app owners if you don’t want that.

When no owner is left, app registrations go to the fallback mailbox. SAML apps go to the notification email addresses in their SAML settings first, then to the fallback mailbox.

Groups can’t own app registrations or Enterprise Apps, only users and service principals can. If a team wants a distribution list notified, add several team members as owners, or put the list in the SAML notification email field.

The runbook doesn’t check whether an owner’s account is disabled. Reassign app ownership during offboarding, or emails will land in a mailbox nobody reads.

FAQ

Does Entra ID notify app owners when a client secret is about to expire?

No. Microsoft Entra has preview recommendations for expiring application and service principal credentials, but they target admins in the Application Administrator role. SAML apps can email a notification address, but app registration owners get nothing. This runbook fills that gap.

How do I find expiring app registration secrets with PowerShell?

Connect to Microsoft Graph and compare each credential’s EndDateTime with today’s date. A quick one-off check for the next 30 days:
Connect-MgGraph -Scopes "Application.Read.All"
Get-MgApplication -All | ForEach-Object { $app = $_ @($app.PasswordCredentials) + @($app.KeyCredentials) | Where-Object { $_.EndDateTime -lt (Get-Date).AddDays(30) } | Select-Object @{n='App';e={$app.DisplayName}}, DisplayName, EndDateTime }

Does it check SAML SSO certificates on Enterprise Apps?

Yes. It checks the active signing certificate of every Enterprise App configured for SAML SSO.

What permissions does the runbook need?

Application.Read.All and User.Read.All as Microsoft Graph application permissions, plus Mail.Send scoped to the sender mailbox through Exchange Online RBAC for Applications.

Why do all the emails go to the fallback address?

Usually User.Read.All is missing. Without it, Graph returns owners without their email address, so every app looks ownerless.

Why does the job fail with “Automation Variable … not found”?

A required variable or the AppMonCert certificate isWhy does the job fail with “Automation Variable … not found”? missing or misspelled. The error names which one. Check App_Reg_IncludeAdmin first.

Why does the job say Get-MgApplication is not recognized?

The Graph modules aren’t imported into the Automation Account, or they were imported for a different runtime version than the runbook uses.

Can I run it from my PC or with Task Scheduler?

No. It uses Get-AutomationVariable and Get-AutomationCertificate, which only exist in Azure Automation, in the cloud sandbox or on a Hybrid Runbook Worker

Conclusion

Entra ID app secret expiry and SAML certificate expiry are small problems that cause big outages. With one runbook, three permissions, a certificate, and a weekly schedule, owners get a clear email before anything breaks, admins get the full picture, and you get your Monday mornings back.

Give it a try, and if you have ideas or questions, drop them in the comments or open an issue on GitHub.

Rate this post