Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
As an administrator, it’s important to proactively manage application credentials to maintain security in your organization. This article shows you how to use PowerShell to view and export a list of applications in Microsoft Entra ID that have expiring secrets or certificates. You learn how to filter results by expiration date, include already expired credentials if needed, and export the data to a CSV file for further review or action.
Prerequisites
To retrieve all applications with expiring secrets and certificates in Microsoft Entra ID, you need:
- A Microsoft Entra user account. If you don't already have one, you can Create an account for free.
- One of the following roles:
- Microsoft Entra PowerShell module installed. Follow the Install the Microsoft Entra PowerShell module guide to install the module.
Export apps
The following script generates applications with expiring secrets and certificates. You define the period to cover and choose whether to include apps with secrets and certificates that already expired.
Connect-Entra -Scopes 'Application.Read.All'
$Applications = Get-EntraServicePrincipal -all
$Logs = @()
$Messages = @{
ExpirationDays = @{
Info = 'Filter the applications to log by the number of days until their secrets expire.'
Prompt = 'Enter the number of days until the secrets expire as an integer.'
}
AlreadyExpired = @{
Info = 'Would you like to see Applications with already expired secrets as well?'
Prompt = 'Enter Yes or No'
}
DurationNotice = @{
Info = @(
'The operation is running and will take longer the more applications the tenant has...'
'Please wait...'
) -join ' '
}
Export = @{
Info = 'Where should the CSV file export to?'
Prompt = 'Enter the full path in the format of <C:\Users\<USER>\Desktop\Users.csv>'
}
}
Write-Host $Messages.ExpirationDays.Info -ForegroundColor Green
$DaysUntilExpiration = Read-Host -Prompt $Messages.ExpirationDays.Prompt
Write-Host $Messages.AlreadyExpired.Info -ForegroundColor Green
$IncludeAlreadyExpired = Read-Host -Prompt $Messages.AlreadyExpired.Prompt
$Now = Get-Date
Write-Host $Messages.DurationNotice.Info -ForegroundColor yellow
foreach ($App in $Applications) {
$AppName = $App.DisplayName
$AppID = $App.Id
$ApplID = $App.AppId
$AppCreds = Get-EntraServicePrincipal -ServicePrincipalId $AppID |
Select-Object PasswordCredentials, KeyCredentials
$Secrets = $AppCreds.PasswordCredentials
$Certs = $AppCreds.KeyCredentials
foreach ($Secret in $Secrets) {
$StartDate = $Secret.StartDateTime
$EndDate = $Secret.EndDateTime
$SecretName = $Secret.DisplayName
$Owner = Get-EntraServicePrincipalOwner -ServicePrincipalId $App.Id
$Username = $Owner.AdditionalProperties.userPrincipalName -join ';'
$OwnerID = $Owner.Id -join ';'
if ($null -eq $Owner.AdditionalProperties.userPrincipalName) {
$Username = @(
$Owner.AdditionalProperties.displayName
'**<This is an Application>**'
) -join ' '
}
if ($null -eq $Owner.AdditionalProperties.displayName) {
$Username = '<<No Owner>>'
}
$RemainingDaysCount = $EndDate - $Now |
Select-Object -ExpandProperty Days
if ($IncludeAlreadyExpired -eq 'No') {
if ($RemainingDaysCount -le $DaysUntilExpiration -and $RemainingDaysCount -ge 0) {
$Logs += [PSCustomObject]@{
'ApplicationName' = $AppName
'ApplicationID' = $ApplID
'Secret Name' = $SecretName
'Secret Start Date' = $StartDate
'Secret End Date' = $EndDate
'Certificate Name' = $Null
'Certificate Start Date' = $Null
'Certificate End Date' = $Null
'Owner' = $Username
'Owner_ObjectID' = $OwnerID
}
}
} elseif ($IncludeAlreadyExpired -eq 'Yes') {
if ($RemainingDaysCount -le $DaysUntilExpiration) {
$Logs += [pscustomobject]@{
'ApplicationName' = $AppName
'ApplicationID' = $ApplID
'Secret Name' = $SecretName
'Secret Start Date' = $StartDate
'Secret End Date' = $EndDate
'Certificate Name' = $Null
'Certificate Start Date' = $Null
'Certificate End Date' = $Null
'Owner' = $Username
'Owner_ObjectID' = $OwnerID
}
}
}
}
foreach ($Cert in $Certs) {
$StartDate = $Cert.StartDateTime
$EndDate = $Cert.EndDateTime
$CertName = $Cert.DisplayName
$RemainingDaysCount = $EndDate - $Now |
Select-Object -ExpandProperty Days
$Owner = Get-EntraServicePrincipalOwner -ServicePrincipalId $App.Id
$Username = $Owner.AdditionalProperties.userPrincipalName -join ';'
$OwnerID = $Owner.Id -join ';'
if ($null -eq $Owner.AdditionalProperties.userPrincipalName) {
$Username = @(
$Owner.AdditionalProperties.displayName
'**<This is an Application>**'
) -join ' '
}
if ($null -eq $Owner.AdditionalProperties.displayName) {
$Username = '<<No Owner>>'
}
if ($IncludeAlreadyExpired -eq 'No') {
if ($RemainingDaysCount -le $DaysUntilExpiration -and $RemainingDaysCount -ge 0) {
$Logs += [pscustomobject]@{
'ApplicationName' = $AppName
'ApplicationID' = $ApplID
'Secret Name' = $Null
'Certificate Name' = $CertName
'Certificate Start Date' = $StartDate
'Certificate End Date' = $EndDate
'Owner' = $Username
'Owner_ObjectID' = $OwnerID
'Secret Start Date' = $Null
'Secret End Date' = $Null
}
}
} elseif ($IncludeAlreadyExpired -eq 'Yes') {
if ($RemainingDaysCount -le $DaysUntilExpiration) {
$Logs += [pscustomobject]@{
'ApplicationName' = $AppName
'ApplicationID' = $ApplID
'Certificate Name' = $CertName
'Certificate Start Date' = $StartDate
'Certificate End Date' = $EndDate
'Owner' = $Username
'Owner_ObjectID' = $OwnerID
'Secret Start Date' = $Null
'Secret End Date' = $Null
}
}
}
}
}
Write-Host $Messages.Export.Info -ForegroundColor Green
$Path = Read-Host -Prompt $Messages.Export.Prompt
$Logs | Export-Csv $Path -NoTypeInformation -Encoding UTF8