Automated Azure AD Credential Expiration Alerts

Automated Azure AD Credential Expiration Alerts

All secrets and certificates created within Azure App Registrations have expiration dates, making it crucial for administrators to stay informed to take timely action. Microsoft does not provide an automated notification for this. However, by leveraging Microsoft Graph API and Power Automate, you can set up automated alerts to notify when secrets and certificates are nearing expiration—or have already expired.

Below is an example e-mail of expiring and expired secrets and certificates generated by Power Automate:

The end-result in e-mail showing expiring secrets, expired secrets, as well as an a csv export of all secrets.

Requirements

You’ll need an app registration that at a minimum has Application.Read.All Permissions. I’ve covered how to create an app registration in this prior blog post, so it’s worth reading if you’re not familiar with the basics.

Process Flow Diagram

At a high-level, here’s is the process of the Power Automate:

Get the Code

You can download the completed Power Automate from my GitHub. Be sure to review the ReadMe file for the installation instructions!

Detailed Explanation of the Flow

Call to Graph API

After the access token is acquired, the /applications endpoint is called. I select only the columns needed to improve query performance:

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

The HTTP Request is inside a Do Until loop since the API call will paginate 100 records at a time by default.

Process the Secrets and Certificates

With the body value response data, I filter on the passwordcredentials array where it is not empty. We only want to get those App Registrations that have secrets. Then, time to loop through each application and it’s secrets with a nested apply to each.

We also make another call to the Graph and fetch the Application’s owner(s). It will return as an array since there can be more than one. I join the owner’s email addresses together with a ‘;’ and append them to the output later. For the secrets, importantly, we need to calculate the date difference from the endDateTime of the secret to now.Using dateDifference with split (to get characters before the “.”) returns the difference in days.

The days to expire is a custom property derived from the datediffence formula in the prior step. However, we take it a step further to check if the result is 0 or contains a “:” as will be the case if a time value is present after the prior split function. If that happens, then it’s 0 days, else it’s the split results from the prior step. The result is casted as a float value since we can have negative values (meaning the secret has already expired!) Finally, append the outputs to the application details array variable.

split(dateDifference(utcNow(),item()?['endDateTime']),'.')
float(if(equals(length(outputs('Date_Diff_Secret')), 0), 0, if(contains(outputs('Date_Diff_Secret')[0], ':'), 0, outputs('Date_Diff_Secret')[0])))

The same logic above is applied to retrieve the certificates.

For the last action in the do until, don’t forget to set the Next Link value. When this value is empty, it’ll break out of the loop.

Filter and Email

At this point, I want to filter the results by filtering the expired and expiring secrets in less than x number days as defined in the “Days Until Expire” variable. We construct two html tables from the results set, including a deep link to the Application in Azure, and print the outputs in the email.

And the email the admin.

Leave a Reply