Do you have an on-prem Active Directory (AD) environment and syncing to Azure Active Directory (AD)? If so, you may have run across a frustrating problem - an on-prem AD user has expired but that user can still access resources protected with Azure AD.

Unfortunately, Azure AD is not aware when an on-prem AD user is expired. This situation can lead to a user accessing cloud services when they should not be allowed to.

To remedy this security risk, you can use PowerShell to find all expired AD accounts and revoke those accounts' Azure AD refresh token.

This article was inspired by Alex Holmeset's informative script on this subject.

Let's break down what it takes to build a PowerShell script to find all expired on-prem AD users, find each account's Azure AD counterpart and revoke their token.

Prerequisites/Requirements

If you intend for the examples in this code to work in your environment, be sure you have the following prerequisites in place ahead of time.

  • Have an on-prem AD environment
  • Have an Azure AD tenant created
  • Have on-prem and Azure AD user accounts synced
  • Are using the AD account expiration feature for various user accounts
  • Are logged into a domain-joined computer with user-read rights
  • Have the Remote Server Administration Tools (RSAT) tools installed on Windows 10
  • Have the Az PowerShell module installed - All examples use v1.8.0 in this article.

Finding Expired AD User Accounts

The first task is finding all on-prem AD user accounts that are disabled. The easiest way to do that is by using the Search-AdAccount cmdlet. This is a cmdlet that allows you to scour on-prem AD many different ways. In this example, you're interested in only finding user accounts that are expired.

Open up a PowerShell console and run Search-AdAccount limiting the scope to only expired user accounts.

$expiredUsers = Search-ADAccount -AccountExpired -UsersOnly

Disabling Expired AD User Accounts

Once you have each expired user account in memory, it's time to disable each account with the Disable-ADAccount cmdlet.

It is not a requirement to disable the expired AD account. Some use cases call for this if you don't intend to use this account in the near future again.

One way to process an action (disabling an AD account) on a set of objects is to use a foreach loop. Set up the foreach loop to disable each expired user account found. The code below passes each user account saved in $expiredUsers to the Disable-AdAccount cmdlet and attempts to disable each one.

foreach ($user in $expiredusers) {
	$user | Disable-ADAccount
}
If you'd rather not be prompted each time when disabling a user, use the -Confirm:$false parameter and value.

Revoking Azure AD User Refresh Tokens

It's time for the final step - actually revoking the Azure AD refresh tokens.

Using the foreach loop created earlier, first add another step inside of the loop to find the on-prem AD account's associated Azure AD account using the Get-AzAdUser cmdlet. Once the associated Azure AD account is found then pass that account to the Revoke-AzureADUserAllRefreshToken cmdlet.

You can see below a script you can use to bring all of these instructions together.

$expiredUsers = Search-ADAccount -AccountExpired -UsersOnly

foreach ($user in $expiredusers) {
  ## disable the on-prem AD account
	$user | Disable-ADAccount
  ## find the associated Azure AD account and the Azure AD refresh token from it
	Get-AzADUser -ObjectId $user.UserPrincipalName | Revoke-AzureADUserAllRefreshToken
}

Next Steps

Now that you have a script to:

  • Find all expired, on-prem, AD user accounts
  • Find each account's Azure AD account
  • Revoke each account's refresh token

...where would this script best be used? Sure, you could run this ad-hoc whenever you want but if you use the user expiration feature, over time, more users will end up being expired. Try to roll this into a scheduled task or via Azure Automation perhaps to keep on top of this problem.