Automate sending email notifications for client secret expiration of App Registration under Microsoft Entra ID

$@chin 380 Reputation points
2023-12-19T15:32:02.8266667+00:00

Is there any way to set up email notifications or alerts for the expiration of any client secret in an app registration on Microsoft Entra ID ?

Microsoft Security | Microsoft Entra | Microsoft Entra ID

6 answers

Sort by: Most helpful
  1. Maksym Vostruhin 10 Reputation points
    2026-07-04T14:00:57.85+00:00

    It's 2026 and the problem is still relevant. I have two solutions.

    The fist is fully in-house thing and could help you setup monitoring if your team uses Azure DevOps, since it fully relies on the pipeline functionality.

    The second one is a third party tool, but it solves the monitoring and reporting in, literally, a few minutes.

    In-house solution: (up to 1h to set it up)

    1. Create a new pipeline in ADO (blank for now)
    2. Create a new service connection in ADO (Project Settings -> Service Connections -> New). Type: Azure Resource Manager, Workload Identity Federation, access to all resource groups. Remember the name of the service connection, you'll need it
    3. Grant permission to read apps data to the service connection. Azure, Entra ID -> App Registration -> Found the one was automatically created for the service connection -> Api Permissions -> Microsoft Graph -> App permissions -> Application.Read.All. After adding it, don't forget to click on the admin consent right above the table with permissions.
    4. Go to the created pipeline now, and paste the code below
    trigger: none
    schedules:
      - cron: "0 6 * * *"    # 06:00 UTC nightly — adjust to your timezone
        displayName: Nightly credential expiry check
        branches:
          include:
            - main
        always: true
    pool:
      vmImage: ubuntu-latest
    variables:
      warnDays: 30
      azureServiceConnection: 'service-connection-name'   # set this to your service connection name
    steps:
      - task: AzureCLI@2
        displayName: 'Check Entra app credential expiry'
        inputs:
          azureSubscription: $(azureServiceConnection)
          scriptType: bash
          scriptLocation: inlineScript
          inlineScript: |
            set -euo pipefail
            THRESHOLD=$(date -u -d "+${WARN_DAYS} days" +%Y-%m-%dT%H:%M:%SZ)
            NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
            echo "Checking for credentials expiring before $THRESHOLD"
            az ad app list --all \
              --query "[].{name:displayName, appId:appId, secrets:passwordCredentials, certs:keyCredentials}" \
              -o json > apps.json
            RESULTS=$(jq --arg threshold "$THRESHOLD" --arg now "$NOW" '
              [.[] |
                .name as $name |
                .appId as $appId |
                (.secrets[]? | select(.endDateTime != null and .endDateTime < $threshold) |
                  {application: $name, appId: $appId, credential: .displayName, type: "Secret", expiresUtc: .endDateTime,
                   status: (if .endDateTime < $now then "EXPIRED" else "Expiring" end)}),
                (.certs[]? | select(.endDateTime != null and .endDateTime < $threshold) |
                  {application: $name, appId: $appId, credential: .displayName, type: "Certificate", expiresUtc: .endDateTime,
                   status: (if .endDateTime < $now then "EXPIRED" else "Expiring" end)})
              ]' apps.json)
            COUNT=$(echo "$RESULTS" | jq 'length')
            echo "Found $COUNT expiring/expired credential(s)"
            echo "$RESULTS" | jq -r '.[] | "\(.status)\t\(.application)\t\(.credential)\t\(.type)\texpires \(.expiresUtc)"' | column -t -s$'\t'
            echo "$RESULTS" > $(Build.ArtifactStagingDirectory)/expiry-report.json
            echo "##vso[task.setvariable variable=expiringCount]$COUNT"
        env:
          WARN_DAYS: $(warnDays)
      - task: PublishBuildArtifacts@1
        displayName: 'Publish expiry report'
        inputs:
          PathtoPublish: '$(Build.ArtifactStagingDirectory)/expiry-report.json'
          ArtifactName: 'expiry-report'
      - task: AzureCLI@2
        displayName: 'Send email via Graph'
        condition: gt(variables['expiringCount'], 0)
        inputs:
          azureSubscription: $(azureServiceConnection)
          scriptType: bash
          scriptLocation: inlineScript
          inlineScript: |
            set -euo pipefail
            BODY_HTML=$(jq -r '
              "<table border=1 cellpadding=6><tr><th>Application</th><th>Credential</th><th>Type</th><th>Status</th><th>Expires (UTC)</th></tr>" +
              (map("<tr><td>" + .application + "</td><td>" + .credential + "</td><td>" + .type + "</td><td>" + .status + "</td><td>" + .expiresUtc + "</td></tr>") | join("")) +
              "</table>"
            ' $(Build.ArtifactStagingDirectory)/expiry-report.json)
            az rest --method POST \
              --uri "https://graph.microsoft.com/v1.0/users/******@yourdomain.com/sendMail" \
              --body "{
                \"message\": {
                  \"subject\": \"Entra credential expiry: $(expiringCount) item(s)\",
                  \"body\": {\"contentType\": \"HTML\", \"content\": $(jq -Rs . <<< \"$BODY_HTML\")},
                  \"toRecipients\": [{\"emailAddress\": {\"address\": \"******@yourdomain.com\"}}]
                }
              }"
    

    As a result, it published a file with expiration report and send via sendMail (Graph, to keep it fully in-house). You need to keep in mind, that the sender should have the license assigned for sending it. If you don't want to mess with it, you can use any 3rd party email sending services, usually it just an api call.

    The fastest way these days: (up to 3 minutes)

    Use AZ Token Watch. It utilizes the same Application.Read.All permission (as the script above, and it never sees secret values) and send email alerts, it's completely free and you don't need to maintain it. I've built it, when had to setup the monitoring system 3-rd time and realized, that I don't want to maintain these scripts anymore.

    Was this answer helpful?

    2 people found this answer helpful.
    0 comments No comments

  2. RobinCM 96 Reputation points
    2024-10-25T17:33:38.8866667+00:00

    Take a look at this: Recommendation to renew expiring application credentials - Microsoft Entra ID | Microsoft Learn

    I had an email a few weeks ago telling me that I had an application credential expiring. When you click the link in the email it takes you to a page on the Azure portal which lists the resource name and ID.

    For info I've got E5 licences.

    Was this answer helpful?

    2 people found this answer helpful.
    0 comments No comments

  3. JamesTran-MSFT 37,256 Reputation points Microsoft Employee Moderator
    2024-01-03T20:17:37.75+00:00

    @Sachin Gupta

    Thank you for your post and I apologize for the delayed response!

    Unfortunately, there isn't a direct way within the Portal to set up notifications or alerts for expiring secrets within an App Registration. However, you should be able to leverage PowerShell or Microsoft Graph to achieve some form of notification for expiring secrets/ certificates, for example:

    1. Export all of your app registrations with expiring secrets and certificates via PowerShell script.
    2. Integrate the PowerShell script into an Azure Logic App or Task Scheduler.
    3. Send email notifications via the Logic App or Task Scheduler with the PowerShell output.

    Additional Links:

    I hope this helps!

    If you have any other questions, please let me know. Thank you for your time and patience throughout this issue.


    If the information helped address your question, please Accept the answer. This will help us and also improve searchability for others in the community who might be researching similar information.

    Was this answer helpful?

    2 people found this answer helpful.

  4. Oguz Kaan Akyalcin 11 Reputation points
    2025-04-15T10:00:42.5633333+00:00

    you may consider creating an account automation on Azure with a PowerShell script and scheduling it to receive email notifications

    Here is the step-by-step guide

    https://wiseservices.co.uk/post/a3a10db6-02b5-4162-9773-cc3e2c618a47

    Was this answer helpful?

    1 person found this answer helpful.
    0 comments No comments

  5. Aeron W. Barhorst 10 Reputation points
    2025-02-20T13:44:21.41+00:00

    Apparently, an E3 license isn't good enough to access the "recommendation to renew expiring application credentials".

    Was this answer helpful?

    1 person found this answer helpful.
    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.