How To Monitor The Azure Active Directory Client Secret Expiration

It’s crucial to maintain continuous operation of live applications at all times. But what if you neglect to update the ClientSecrets that have expired and your program suddenly crashes? Your clients and business will be impacted, and you will receive several letters requesting further action. As the owner of the application, you don’t want any application downtime.

Implementing a PowerShell script with Azure Function to track the expiration of your Azure AD app client secrets and send the appropriate people an email before it expires can help you prevent all of these problems.

I assume you are already familiar with the technologies listed below, but if not, please glance over their official documentation.

Create Azure Timer Trigger

  • Login to Azure Portal
  • Search for Azure Function App and create the resource with required details.
  • Ensure to choose the Function runtime as PowerShell Core
  • Once the resource has been created, select “Timer Trigger” from the Create Trigger drop-down option under the Functions menu in the left pane.


How to change the schedule in Timer Trigger

  • Schedules can be used as the basis for timer triggers if you want to alter the trigger’s timing.
  • Go to the “Code + Test” menu after clicking the name of your function on the next screen.
  • Change the schedule timing by selecting function.json from the files menu and looking for the “schedule” item in the json file.
  • Learn more about the which expressions to use for the timing, please have a look at NCRONTAB expressions



How to enable AZ PowerShell module in Azure Functions

By default, AZ module is supported by Azure functions when working with Azure Resources. The steps to enable it are listed below.

Have a look at Azure PowerShell module commands to learn more about it.

  • Go to your function app and select App Files from the left pane.
  • From the files dropdown, choose “requirements.psd1,” then uncomment the Az module as shown in the screenshot below. You can alter it if you wanted a specific Az module version.

Enabling Managed Identity in Azure Functions

To allow our Azure Function app access to the Active Directory, we would need to enable managed identity. For more information on how to enable it, please look at utilize managed identities for App Service and Azure Functions.


How to assign Application administrator permission to Azure Managed identity

Go to Azure Active Directory and in the landing, page select “Roles and administrators”

Select “Application administrator” on the following screen, and then click “Add Assignments.”

Then perform a search on your managed identity and approve the request. You may discover your Azure function app identity under assignments after providing permission as shown below.



Now that everything is ready and set up for our implementation, let’s look at the actual script to carry it out.

PowerShell Code in Azure Function to monitor Azure AD Client Secrets

Add the Webhook post URL and expiration days to the function app’s setup as shown below so that the function code may access them.


  • Now that client secrets will expire before the specified term, our script will read all AD apps and retrieve meta information such as Description, ExpiryDate, AppID, AppObjectID, AppName, and Key Identifier.
  • Even if there are many client secrets that are about to expire in a single Azure AD app. It will also be given back in the resultant array as a distinct object.
  • The Array object will be posted to WebHook in the last few lines of the code.
  • This is the complete code. select “Code + Test” from your Timer Trigger Function and enter the following code in the code editor.
# Input bindings are passed in via param block.

#secret expiration date filter (for example 30 days)
$LimitExpirationDays = $env:LimitExpirationDays

$SecretsToExpire =@()

#Retrieving the list of secrets that expires in the above range of days
Get-AzADApplication | ForEach-Object {
    $app = $_
        Get-AzADAppCredential -ObjectId $_.Id
    ) | Where-Object {
        $_.EndDateTime -lt (Get-Date).AddDays($LimitExpirationDays)
    } | ForEach-Object {
         $expiringSecret = @{
            AppName = $app.DisplayName
            AppObjectID = $app.Id
            AppApplicationId = $app.AppId
            SecretDisplayName = $_.DisplayName
            SecretKeyIdentifier = $_.KeyId
            SecretEndDate = $_.EndDateTime
        $SecretsToExpire += $expiringSecret

#Printing the list of secrets that are near to expire
if($SecretsToExpire.Count -EQ 0) {
    Write-Output "No secrets found that will expire in this range"
else {
    Write-Output "Secrets that will expire in this range:"
    Write-Output $SecretsToExpire.Length
    Write-Output $SecretsToExpire | ConvertTo-Json

    $headers = @{
    'Content-Type' = 'application/json'

    if($SecretsToExpire.Length -EQ 1){
    Invoke-RestMethod -Method 'Post' -Headers $headers -Uri $env:LogicApp_API_Url -Body (ConvertTo-Json @($SecretsToExpire))
    Invoke-RestMethod -Method 'Post' -Headers $headers -Uri $env:LogicApp_API_Url -Body ($SecretsToExpire | ConvertTo-Json)


The user notification step is the following one, and it can be done using any webhook or API URL that receives your PowerShell POST request and processes the Request data to send emails. Going with Azure Logic Apps will simplify this approach because it comes with Mailing connections by default.

Our focus right now is on the client secrets that are about to expire because it is always being monitored.

Note: If you don’t want to receive the emails or run the trigger, go to your Timer Trigger -> Overview page and Disable the Function temporarily.




Submit a Comment

Your email address will not be published. Required fields are marked *


Select Categories