1. Home
  2. Lab library
  3. IB-WORKLOAD

Audit App Registration Secrets and Certificates in Entra ID

App registrations sign in with client secrets and certificates that are easy to create and easy to forget. In this lab you inventory every application credential with Microsoft Graph PowerShell, flag expired, soon to expire and long-lived secrets, find apps…

Level Intermediate Time about 90 minutes Updated
Quick answer

App registrations sign in with client secrets and certificates that are easy to create and easy to forget. In this lab you inventory every application credential with Microsoft Graph PowerShell, flag expired, soon to expire and long-lived secrets, find apps with no owner, rotate one credential safely and review options that reduce the need for secrets.

Key takeaways

  • Application credentials do not use MFA, so a leaked secret is a working login
  • Inventory both passwordCredentials and keyCredentials for every application
  • Add the new credential and deploy it before you remove the old one
  • Prefer managed identities, federated credentials or certificates over client secrets

Why this lab matters

Users get MFA, Conditional Access and sign-in risk checks. Applications mostly get a secret string and a long expiry date. Attackers know this, which is why stolen application credentials appear in so many cloud incidents. The first control is simple: know every credential you have, who owns it and when it expires.

Application credential hygiene, from inventory to policy01Inventory credentialsSecrets and certificates02Flag the risksExpired, long-lived, no owner03Assign ownersTwo named people per app04Rotate safelyAdd new, deploy, remove old05Reduce secretsManaged and federated identity
Application credential hygiene, from inventory to policy

What you need

  • A test tenant with a few app registrations. Create two or three and add secrets with different expiry dates so you have data.
  • The Microsoft Graph PowerShell SDK and the Application Administrator or Cloud Application Administrator role.

Step 1: Inventory every credential

Connect-MgGraph -Scopes "Application.Read.All"

$now = Get-Date
$report = foreach ($app in Get-MgApplication -All -Property Id, AppId, DisplayName, PasswordCredentials, KeyCredentials) {
  $owners = (Get-MgApplicationOwner -ApplicationId $app.Id -All).Count
  foreach ($c in @($app.PasswordCredentials) + @($app.KeyCredentials)) {
    if (-not $c) { continue }
    [pscustomobject]@{
      App          = $app.DisplayName
      AppId        = $app.AppId
      Type         = if ($c.PSObject.Properties.Name -contains 'Hint') { 'Secret' } else { 'Certificate' }
      KeyId        = $c.KeyId
      Start        = $c.StartDateTime
      End          = $c.EndDateTime
      DaysLeft     = [int]($c.EndDateTime - $now).TotalDays
      LifetimeDays = [int]($c.EndDateTime - $c.StartDateTime).TotalDays
      Owners       = $owners
    }
  }
}
$report | Sort-Object DaysLeft | Format-Table App, Type, DaysLeft, LifetimeDays, Owners
$report | Export-Csv .\app-credentials.csv -NoTypeInformation

Step 2: Flag the risks

$report | Where-Object DaysLeft -lt 0          # expired, safe to remove once unused
$report | Where-Object { $_.DaysLeft -ge 0 -and $_.DaysLeft -le 30 }   # outage risk
$report | Where-Object LifetimeDays -gt 365    # long-lived
$report | Where-Object Owners -eq 0            # nobody to ask
FindingWhy it mattersAction
ExpiredClutter that hides real problemsRemove
Expires in 30 daysThe app will stop workingRotate now
Lifetime over one yearA leak stays useful for longerReplace with a shorter one
No ownerNo one can confirm whether it is neededFind and assign two owners

Step 3: Check whether a credential is still used

Before you remove anything, look at the service principal sign-in logs. In the Entra admin centre open Sign-in logs and choose the Service principal sign-ins tab, then filter by the application. If the logs are in Log Analytics you can see which credential was used:

AADServicePrincipalSignInLogs
| where TimeGenerated > ago(30d)
| summarize LastUsed = max(TimeGenerated), SignIns = count()
    by AppId, ServicePrincipalName, ServicePrincipalCredentialKeyId

Step 4: Rotate one secret safely

  1. Add a new secret with a short lifetime:
    Connect-MgGraph -Scopes "Application.ReadWrite.All"
    $app = Get-MgApplication -Filter "displayName eq 'lab-reporting-app'"
    $new = Add-MgApplicationPassword -ApplicationId $app.Id -PasswordCredential @{
      displayName = "rotated-2026-11"
      endDateTime = (Get-Date).AddDays(90)
    }
    $new.SecretText   # shown once. Store it in a vault, not in a script
  2. Update the application or pipeline that uses it and confirm it signs in with the new credential.
  3. Remove the old one by its key ID:
    Remove-MgApplicationPassword -ApplicationId $app.Id -KeyId "<old KeyId from the report>"
Warning

Never paste a secret into a ticket, chat or source repository. If one has been exposed, treat it as compromised and rotate it straight away.

Step 5: Reduce the number of secrets

  • Managed identities for workloads that run in Azure. There is no credential for you to store or rotate.
  • Federated identity credentials for GitHub Actions, Kubernetes and other platforms that can present their own token.
  • Certificates where a credential is unavoidable, with the private key held in a vault or hardware module.
  • Application management policies in Entra, which can block new secrets or cap their lifetime across the tenant. These need Workload Identities Premium licences for some restrictions, so check the current licensing before you plan on them.
Verify

Run the Step 1 script again. The lab is complete when there are no expired credentials, nothing expires within 30 days, every app has at least one owner and your rotated app still signs in.

Evidence to keep

  • The before and after CSV exports.
  • The list of owners you assigned.
  • A sign-in log entry showing the rotated app authenticating with the new key ID.

Clean up

Delete the test app registrations and any stored test secrets.

Frequently asked questions

How do I find expiring client secrets in Entra ID?

Use Microsoft Graph PowerShell to read passwordCredentials and keyCredentials from every application with Get-MgApplication, then compare each endDateTime with today's date. The script in this lab exports the result to CSV.

Is a client secret or a certificate more secure for an app registration?

A certificate is generally safer because the private key can stay inside a vault or hardware module and is never sent to Entra ID. A client secret is a shared string that is easy to copy and leak. A managed identity or federated credential is better than both where it is available.

How long should an app registration secret last?

Keep lifetimes as short as your rotation process allows. Many teams use 90 to 180 days. Anything longer than a year should be replaced, and an application management policy can enforce a maximum.

What happens if I delete a secret that is still in use?

The application will fail to authenticate until it is given a valid credential. Check service principal sign-in logs first, and always add and deploy the new credential before removing the old one.

Built and published by Muhammad Rizwan Afzal for Identity Bytes. Run every lab against a disposable test tenant, never production.