APP-02: Enforce Application Credential Expiration

Overview

Long-lived or non-expiring client secrets are a supply chain attack risk. If a secret is leaked, it remains valid indefinitely until manually revoked. Rotating credentials on a regular schedule limits the window of exposure from compromised secrets. Certificate-based authentication or managed identities are preferred over client secrets because they reduce the risk further.

TrueConfig detects app registrations whose client secrets have no expiration date set, or whose expiration date exceeds 12 months from the creation date. Remediation is manual: an admin must remove non-expiring or over-long secrets and replace them with secrets that expire within 12 months. This control is rated critical severity.

Prerequisites

Required Roles

  • Global Administrator or Application Administrator - Can manage credentials on any app registration
  • Cloud Application Administrator - Can manage credentials on most app registrations
  • Application Owner - Can manage credentials on apps they own

Required Licenses

No premium Entra ID license is required for this control. Any Microsoft Entra ID tier supports credential management on app registrations. An appropriate admin role (see above) is still required to perform the steps.

Time Estimate

  • Audit across all apps: 30-60 minutes (depending on number of app registrations)
  • Per-app remediation: 10-20 minutes (includes updating the app's configuration with the new secret)
  • Migration to certificates: varies by application

Step-by-Step Instructions

Step 1: Enumerate Secrets and Their Expiration Dates

TrueConfig identifies non-compliant secrets automatically. You can also enumerate them directly.

Method A: Entra Admin Center (Per App)

  1. Navigate to Microsoft Entra admin center (https://entra.microsoft.com)
  2. Expand IdentityApplicationsApp registrations
  3. Click on an application
  4. Select Certificates & secrets in the left menu
  5. Under Client secrets, review the Expires column
  6. Flag any secret with no expiry or an expiry more than 12 months after its creation date

Method B: PowerShell (Recommended for Bulk Audit)

This script lists all client secrets across all app registrations with their expiration dates:

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

$apps = Get-MgApplication -All -Property Id,DisplayName,AppId,PasswordCredentials

$results = foreach ($app in $apps) {
    foreach ($secret in $app.PasswordCredentials) {
        $lifetime = $null
        if ($secret.StartDateTime -and $secret.EndDateTime) {
            $lifetime = ($secret.EndDateTime - $secret.StartDateTime).Days
        }

        $nonExpiring  = (-not $secret.EndDateTime)
        $overLimit    = $lifetime -and ($lifetime -gt 365)

        if ($nonExpiring -or $overLimit) {
            [PSCustomObject]@{
                AppDisplayName = $app.DisplayName
                AppId          = $app.AppId
                SecretHint     = $secret.DisplayName
                StartDate      = $secret.StartDateTime
                EndDate        = $secret.EndDateTime
                LifetimeDays   = $lifetime
                Issue          = if ($nonExpiring) { "No expiration" } else { "Exceeds 12 months ($lifetime days)" }
            }
        }
    }
}

$results | Sort-Object Issue, AppDisplayName | Format-Table -AutoSize
$results | Export-Csv -Path "OverdueSecrets.csv" -NoTypeInformation
Write-Host "Found $($results.Count) non-compliant secrets"

Method C: Microsoft Graph API

GET https://graph.microsoft.com/v1.0/applications?$select=id,displayName,appId,passwordCredentials

For each application, inspect passwordCredentials[].endDateTime. A null value means no expiration; calculate the delta between startDateTime and endDateTime to check whether the lifetime exceeds 365 days.

Step 2: Prioritize Remediation

Address the highest-risk secrets first:

PriorityCriteria
ImmediateSecret has no expiration date at all
HighSecret expires more than 24 months from creation, or is already expired
MediumSecret expires between 12 and 24 months from creation

Step 3: Remove Non-Compliant Secrets and Create Replacements

Work through each flagged app. Do not delete the old secret until the application has been updated to use the new one.

Via Entra Admin Center

  1. In App registrations, open the application
  2. Select Certificates & secrets
  3. Under Client secrets, click + New client secret
  4. Enter a description and set the expiration to 12 months (or less)
  5. Click Add
  6. Copy the secret value immediately (it is only shown once)
  7. Update the application's configuration or key vault with the new secret value
  8. Verify the application is working with the new secret
  9. Return to Certificates & secrets and delete the old non-compliant secret

Via PowerShell (Add New Secret)

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

$appObjectId = "<app-registration-object-id>"

$secretParams = @{
    PasswordCredential = @{
        DisplayName = "Rotated $(Get-Date -Format 'yyyy-MM-dd')"
        EndDateTime = (Get-Date).AddMonths(12)
    }
}

$newSecret = Add-MgApplicationPassword -ApplicationId $appObjectId -BodyParameter $secretParams
Write-Host "New secret value (copy now): $($newSecret.SecretText)"

Via PowerShell (Remove Old Secret)

# Use the KeyId from the PasswordCredentials list
Remove-MgApplicationPassword -ApplicationId $appObjectId -KeyId "<old-secret-key-id>"
Write-Host "Old secret removed"

Step 4: Consider Migration to Certificate or Managed Identity

Client secrets are the least preferred credential type. Where feasible, migrate to a more secure alternative:

  • Managed identities: Best for Azure-hosted workloads. No secret to manage at all.
  • Certificate credentials: More secure than secrets; the private key never leaves your key vault. Use keyCredentials on the app registration and store the private key in Azure Key Vault.
  • Workload identity federation: For CI/CD pipelines and GitHub Actions workflows; eliminates secrets entirely.

Evaluate each credentialed app for feasibility of migration as you work through the backlog.

Step 5: Verify TrueConfig No Longer Flags the App

After replacing secrets and removing non-compliant ones, TrueConfig re-evaluates on its next scan cycle. Confirm the app no longer appears in the APP-02 findings list.


Verification Checklist

  • All non-expiring secrets have been removed
  • All replacement secrets have expiration dates of 12 months or less
  • Applications have been updated and verified to work with the new secrets
  • Old non-compliant secrets have been deleted after confirming the replacement works
  • TrueConfig APP-02 findings list is clear (or remaining items have a documented remediation date)
  • Apps eligible for managed identity or certificate auth have been migrated or scheduled for migration
  • Secret rotation is scheduled before the new 12-month expiry (set calendar reminders or Key Vault alerts)

Troubleshooting

Issue: Application breaks after rotating the secret

Cause: The old secret was deleted before the application was updated, or the new secret was not saved correctly.

Solution:

  1. If the old secret still exists (or is within the Entra soft-delete window), restore it temporarily
  2. Update the application configuration with the correct new secret value
  3. Test the application, then delete the old secret

Issue: Cannot determine where the secret is used

Cause: The application may be a third-party SaaS integration or a legacy automation script without documentation.

Solution:

  1. Search your key vaults and CI/CD secrets stores for the app's client ID or secret hint name
  2. Review sign-in logs for the service principal to identify the source IP or user agent
  3. Contact the application owner (see APP-01) for guidance
  4. If no active use is found, disable the service principal and monitor for failures before deleting the secret

Issue: Secret was created by an external vendor

Cause: A third-party integration created its own app registration and credentials.

Solution:

  1. Contact the vendor to request they rotate to a compliant secret
  2. If the vendor cannot comply, evaluate whether a managed identity or federated credential can replace the integration

Issue: App registration has many secrets, some expired

Cause: Secrets accumulate over time without a cleanup process.

Solution:

  1. Delete all expired secrets first (they are no longer usable but add noise)
  2. Identify which active secrets are non-compliant and rotate them
  3. Establish a naming convention for secrets (e.g., Rotated YYYY-MM) to track rotation history

Issue: Graph API shows endDateTime: null but Entra portal shows an expiry

Cause: Older secrets created before Microsoft enforced expiration may store the value differently.

Solution: Treat any secret with endDateTime: null from the Graph API as non-expiring and rotate it. The portal display may reflect a default UI value rather than a stored constraint.


Related Resources


Last updated: January 2025