How to Find Inactive User Accounts in Active Directory

In this guide, I’ll show you how to find inactive users in Active Directory.

Find Inactive Users in Active Directory with PowerShell

In this example, I’ll use PowerShell to find users inactive for 90 days or longer.

  1. Open PowerShell as Administrator:

  2. Copy and Paste the command below:

    $When = ((Get-Date).AddDays(-90)).Date
    Get-ADUser -Filter {LastLogonDate -lt $When} -Properties * | select-object samaccountname,givenname,surname,LastLogonDate
  3. Export Inactive users:

    To export the list of inactive users use this command

    $When = ((Get-Date).AddDays(-90)).Date
    Get-ADUser -Filter {LastLogonDate -lt $When} -Properties * | select-object samaccountname,givenname,surname,LastLogonDate | export-csv -path c:\temp\inactiveusers.csv

Option#2 Find All Unused Accounts with the AD Cleanup Tool

In this example, I’ll use the AD Cleanup Tool to find unused and inactive user accounts.

Step 1. Select the inactive time range (default is last 90 days) and click “Run”

Step 2. To find unused accounts check “Users with no logons” and click “Run”. These accounts will have no lastLogonTimestamp.

How are Inactive User Accounts Identified?

This part is a little long but it explains what user attribute is used to find inactive user accounts. If you are not interested in this then skip to the examples.

User accounts have an attribute called “lastLogonTimeStamp” the purpose of this attribute is to help identify inactive user and computer accounts. Yes, it can be used for computer accounts also.

There are certain logon types that will update the lastLogonTimeStamp attribute they are, Interactive, Network, and Service logons. Interactive logon is what he cares about, this is when someone logs on at a console.

Let’s look at this attribute in ADUC GUI.

Open an account, click on the Attribute Editor tab, and go down to the lastLogonTimestamp attribute.

What is the lastLogon value used for?

You can see in the above screenshot there is also a lastLogon value, you will also see this when using PowerShell. The lastLogon value is not replicated to all domain controllers where the lastLogonTimestamp is. This is important because with the lastLogon attribute you would have to query every domain controller to find out when a user logged on. Microsoft understood this and that is why they introduced the lastLogonTimestamp attribute way back in 2003.

You could technically use the lastLogon to find an inactive account but it’s much more difficult.

Now let’s look at this value with PowerShell.

For some reason, Microsoft renamed this value to LastLogonDate in PowerShell.

Why I have no idea but it’s the same value. If you happen to know why Microsoft renamed it in PowerShell please comment below.

Open up PowerShell and run this command.

get-aduser -identity username -properties *

Here is a screenshot of the same account in my domain.

LastLogonDate in PowerShell

You can see that lastLogonTimestamp and LastLogonDate have the same data and time.

Just remember this.

PowerShell = LastLogonDate
ADUC GUI = lastLogonTimestamp

Using these attributes we can search Active Directory for inactive user accounts.

If you want to know all the technical nerdy stuff about the lastlogonTimestamp attribute then check out this article by Ned Pyle (Microsoft employee) – The LastLogonTimeStamp Attribute – What it was designed for and how it works

Why You Should be Removing Inactive User Accounts

Security is the #1 reason for cleaning up inactive user accounts. Here is the complete list.

  1. Security Risks CIS controls #5 says “There are many ways to covertly obtain access to user accounts, including weak passwords, accounts still valid after a user leaves the enterprise, dormant or lingering test accounts, shared accounts that have not been changed in months or years, service accounts embedded in applications for scripts” I highly recommend you download the CIS controls it is a great source to help defend and secure environments.
  2. Inventory & Tracking Issues – Active Directory is a centralized database. Not only can you use it to track your assets but it can be integrated with other systems for a complete asset management solution. If you don’t cleanup your AD assets then your inventory system will inaccurate.
  3. Ease of management – Kinda along the same lines as#2. A cluttered AD environment leads to a difficult and stressful environment to manage. Think about running a PowerShell script or trying to deploy software to hundreds of computers or users. You will get a lot of returned errors when trying to manage an environment with stale and inactive accounts.
  4. Data Integrity – A lot of these have the same thing, data integrity. Again AD is a centralized database and can be integrated with many systems. If the data in AD is incorrect then all systems connected to AD will be incorrect.
  5. Licensing – Here is a real world exampe. Your AD User accounts sync with a 3rd party system such as McAfee. Mcafee charges you based on user accounts. If you have hundreds of inactive accounts syncing with 3rd party products you could be paying for a lot of extra licenses you don’t need. This is the case when syncing AD with cloud products also.

Best Practices for Removing Inactive User Accounts

Here are some best practices for cleaning up inactive users or computer accounts.

  • Never immediately remove accounts that are identified as inactive. Disabled them first for at least 30 days (longer the better).
  • Search for accounts with a lastLogonTimestamp that is 45 days or older, meaning the AD account shows no logon activity for 45 days or longer.
  • Disable the accounts for at least 30 days, I typically go with 60. With remote access, VPNs, laptops sometimes AD doesn’t get updated. By disabling an account first it’s very easy to re-enable it and give the user their access back.
  • Add a description to the account with the date disabled and your initials. This is very helpful for other admins in case someone asks why an account is disabled.
  • An inactive on premise account might not mean an inactive Office 365 account. This would be for hybrid environments that sync with Office 365. The disabling of the account vs immediately deleting is critical for these types of environments. You could have users working from home that never authenticate to the on prem AD environment but log into office 365 daily.
  • Run the cleanup process every month.

Example 1: Find Inactive User Accounts with PowerShell

To find inactive accounts with PowerShell you will need the RSAT tools installed or run these commands on the domain controller.

All of these examples use the LastLogonDate attribute that I went over in the first part of this article.

Find inactive accounts in the last 60 days


$When = ((Get-Date).AddDays(-60)).Date
Get-ADUser -Filter {LastLogonDate -lt $When} -Properties * | select-object samaccountname,givenname,surname,LastLogonDate

Find inactive accounts in the last 30 days


$When = ((Get-Date).AddDays(-30)).Date
Get-ADUser -Filter {LastLogonDate -lt $When} -Properties * | select-object samaccountname,givenname,surname,LastLogonDate

Here is an example from my domain.

PowerShell inactive accounts in last 30 days

You can export the results to CSV by adding | export-csv -path c:\ps\inactiveusers.csv

$When = ((Get-Date).AddDays(-30)).Date
Get-ADUser -Filter {LastLogonDate -lt $When} -Properties * | select-object samaccountname,givenname,surname,LastLogonDate | export-csv -path c:\ps\inactiveusers.csv

To limit the scope to an organizational unit use the SearchBase parameter with the distinguished name of the OU.

$When = ((Get-Date).AddDays(-30)).Date
Get-ADUser -Filter {LastLogonDate -lt $When} -SearchBase "OU=Accounting,OU=ADPRO Users,DC=ad,DC=activedirectorypro,DC=com" -Properties * | select-object samaccountname,givenname,surname,LastLogonDate

Find inactive users and disable the accounts

$When = ((Get-Date).AddDays(-30)).Date
Get-ADUser -Filter {LastLogonDate -lt $When} -Properties * | select-object samaccountname,givenname,surname,LastLogonDate | Disable-ADAccount

In the above example, I added | Disable-ADAccount at the end to disable all inactive accounts.

You can also use these commands to search computer accounts just change Get-ADUser to Get-ADComputer

As you can see It’s easy to identify inactive user accounts with PowerShell by filtering on the user’s LastLogonDate. If you are into PowerShell you can create a very powerful tool for cleaning up AD.

If you are not into PowerShell or just want a simple GUI tool then check out example 2.

Example 2: Find Inactive User Accounts with the AD Cleanup Tool

The AD Cleanup Tool makes it extremely easy to find inactive user accounts. The tool can also be used to find inactive computers in Active Directory. I also added filters to quickly find expired users, disabled and users with no logon history. These are often forgotten accounts that also should be part of the cleanup process.

Let’s look at an example

To find all inactive accounts for the last 30 days just enter 30 in the search options and click run. You can enter any number into the search options box.

Search inactive accounts in the last 30 days

By default, this tool will display both inactive users and computers. To view just user accounts, uncheck “show Computers” from the filters dropdown.

Change the filter to list just user accounts

This searches the entire domain.

You can limit the search by choosing an OU or group. For example, I want to check for inactive accounts in all of my accounting security groups. I click browse and now I can select all my groups or any OUs.

Select OU or groups to search

To disable or move the accounts, select them and then click the action button.

I’m going to move these accounts to an Inactive OU I created. I click the move button and then select the OU.

Select OU to move accounts into

Now I’ll check ADUC to verify the accounts have been moved. This makes it easy to see all the accounts that I’m going to disable because they are identified as inactive.

If you wanted to find all disabled user accounts, just drop down the filters list and select disabled users.

Display all disabled user accounts

In the screenshot above you can also quickly display all expired user accounts and users with no logon history by simply selecting them in the filter. You can then take action on these accounts by moving or disabling them.

There are a lot of options with this tool and the easy to use interface saves you valuable time when it comes to cleaning up your AD environment.

Summary

I showed you two examples for finding and removing inactive user accounts in Active Directory. I highly recommend you add this to your monthly maintenance checklist. Security is a big concern with Active Directory but as I pointed out there are several reasons why this is an important task. PowerShell is a great option for finding inactive accounts but does require knowledge of scripting. For those that are not into scripting or just want a quick and simple solution, there is the AD Cleanup GUI Tool.

5 thoughts on “How to Find Inactive User Accounts in Active Directory”

  1. Hi Robert,

    Thank you for sharing these incredibly useful tips! Is it possible to use two -Filter checkpoints – one on LastLogonDate for 90 days inactivity, one on Title – with one Get-ADUser cmdlet?

    Regards

    Reply
    • Yes, you can have multiple filters using get-aduser

      example.
      Get-ADUser -Filter {(LastLogonDate -lt $When) -and (title -eq “HR Specialist”)} -Properties * | select-object samaccountname,givenname,surname,LastLogonDate

      Reply
  2. You mentioned “Add a description to the account with the date disabled”. Can a note like that be done in the script as well?

    Reply
  3. Path is incorrect for the csv commands.
    Should be:
    c:\ps\inactiveusers.csv
    rather than:
    c:\ps|inactiveusers.csv

    Thanks for the tips! I appreciate your articles.

    Reply

Leave a Comment