Microsoft Entra ID security

How to find expiring app secrets in Microsoft Entra ID

List app registration secrets and certificates near expiry with Microsoft Graph PowerShell, check 1 app in the Entra admin centre, or use Altivane's Applications report for a rated list.

By the Published Updated

To find expiring app secrets in Microsoft Entra ID, list the secrets and certificates on each app registration and keep those whose end date falls inside your warning window, such as the next 90 days. Microsoft Graph returns a secret's name and dates, never its value, so you can see what is about to lapse but not read the secret. The admin centre shows 1 app at a time.

Choose the method that fits the job
MethodBest fit
PowerShellA tenant-wide CSV of expired and expiring secrets and certificates on app registrations.
Admin centreChecking the credentials of 1 app you already know, or Microsoft's own list of those expiring soon.
AltivaneRecommended for recurring reviews, with expired and expiring credentials rated against a threshold.

Before you start

Use an account in a role that can list applications, such as Global Reader, Security Administrator, Cloud Application Administrator or Application Administrator. The PowerShell example requests Application.Read.All, the least privileged permission for listing applications; your organisation may require administrator consent.

The examples cover app registrations only, so the certificates on enterprise applications, such as SAML signing certificates, are left out, and a credential with no end date is skipped. They read and export; they do not renew, remove or change any credential.

Option 1

Find expiring app secrets with PowerShell

Install the modules once, then connect and export every secret and certificate that has expired or expires inside the window. Change $days to widen or narrow it.

PowerShell
# Install once, if the modules are not already installed.
Install-Module Microsoft.Graph.Authentication, Microsoft.Graph.Applications -Scope CurrentUser
PowerShell
$ErrorActionPreference = 'Stop'
$days = 90
$now = (Get-Date).ToUniversalTime()
$limit = $now.AddDays($days)
Connect-MgGraph -Scopes 'Application.Read.All' -NoWelcome
try {
    $properties = 'id', 'appId', 'displayName', 'passwordCredentials', 'keyCredentials'
    $apps = Get-MgApplication -All -Property $properties
    $report = @(foreach ($app in $apps) {
        $groups = @{ Secret = $app.PasswordCredentials; Certificate = $app.KeyCredentials }
        foreach ($type in $groups.Keys) {
            foreach ($credential in $groups[$type]) {
                if (-not $credential.EndDateTime) { continue }
                $end = $credential.EndDateTime.ToUniversalTime()
                if ($end -le $limit) {
                    [pscustomobject]@{
                        Application = $app.DisplayName
                        AppId       = $app.AppId
                        Type        = $type
                        Name        = $credential.DisplayName
                        EndDateTime = $end
                        DaysLeft    = [int][math]::Floor(($end - $now).TotalDays)
                        Status      = if ($end -lt $now) { 'Expired' } else { 'Expiring' }
                    }
                }
            }
        }
    })
    if ($report.Count -eq 0) {
        Write-Output "No app credentials have expired or expire within $days days."
    } else {
        $report | Sort-Object EndDateTime |
            Export-Csv -Path './expiring-app-credentials.csv' -NoTypeInformation -Encoding utf8
        Write-Output "$($report.Count) app credentials have expired or expire within $days days."
    }
} finally {
    Disconnect-MgGraph | Out-Null
}

The script keeps expired credentials as well as those still to come, soonest end date first, with a negative DaysLeft for the ones already past. Set $days to 30 for a tighter list.

Check a single app

Reconnect with Connect-MgGraph, then read 1 app's secrets and certificates. The main export above disconnects when it finishes.

PowerShell
# Run while connected to Microsoft Graph. Replace the example app name.
$filter = "displayName eq 'Contoso Payroll'"
$props = 'id,displayName,passwordCredentials,keyCredentials'
$app = Get-MgApplication -Filter $filter -Property $props
$app.PasswordCredentials | Select-Object DisplayName, StartDateTime, EndDateTime
$app.KeyCredentials | Select-Object DisplayName, Type, StartDateTime, EndDateTime

Option 2

Check app credentials in the admin centre

  1. Sign in to the Microsoft Entra admin centre for the correct tenant.
  2. Go to Entra ID > App registrations and select the application.
  3. Select Certificates & secrets.
  4. Open the Client secrets tab and the Certificates tab, and read when each one expires.

For a list across the tenant, go to Entra ID > Overview, select the Recommendations tab and open Renew expiring application credentials. Its Impacted resources table names each app and its ID. Microsoft marks it as a preview, and Reports Reader, Security Reader and Global Reader can view it.

This suits 1 app, or a quick look at what Microsoft is flagging. The recommendation looks 30 days ahead, so for every end date in a list to sort or keep, export with PowerShell or a report.

Common questions

Why can I not see the secret itself?

Microsoft shows a secret's value only when it is created, and never again once you leave that page. Graph returns its name and dates. If the value is lost, add a new secret, update whatever uses it, then remove the old one.

Why does Microsoft's recommendation list fewer credentials than my export?

The recommendation covers app registrations and looks 30 days ahead. Credentials whose end date has passed show as completed, so a list of everything expired or due in 90 days is longer.

Who should I ask to renew a credential?

The app's owners. Altivane lists them beside each credential and lists registrations with no owner recorded in App Registrations Without Owners. Where an owner has left, check the account first with how to find inactive users.

Microsoft references

Technical references checked on 5 October 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.

Talk to us about Altivane

Questions, or pricing? Get in touch.

Contact us