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)
- Navigate to Microsoft Entra admin center (https://entra.microsoft.com)
- Expand Identity → Applications → App registrations
- Click on an application
- Select Certificates & secrets in the left menu
- Under Client secrets, review the Expires column
- 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:
| Priority | Criteria |
|---|---|
| Immediate | Secret has no expiration date at all |
| High | Secret expires more than 24 months from creation, or is already expired |
| Medium | Secret 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
- In App registrations, open the application
- Select Certificates & secrets
- Under Client secrets, click + New client secret
- Enter a description and set the expiration to 12 months (or less)
- Click Add
- Copy the secret value immediately (it is only shown once)
- Update the application's configuration or key vault with the new secret value
- Verify the application is working with the new secret
- 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
keyCredentialson 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:
- If the old secret still exists (or is within the Entra soft-delete window), restore it temporarily
- Update the application configuration with the correct new secret value
- 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:
- Search your key vaults and CI/CD secrets stores for the app's client ID or secret hint name
- Review sign-in logs for the service principal to identify the source IP or user agent
- Contact the application owner (see APP-01) for guidance
- 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:
- Contact the vendor to request they rotate to a compliant secret
- 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:
- Delete all expired secrets first (they are no longer usable but add noise)
- Identify which active secrets are non-compliant and rotate them
- 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
- Add credentials to an application in Microsoft Entra ID
- Best practices for application credentials
- Managed identities for Azure resources
- Workload identity federation
- Microsoft Graph PowerShell: Add-MgApplicationPassword
- Related controls: APP-01 (Application Ownership for Apps with Credentials)
Last updated: January 2025