Skip to content

Microsoft 365 Inactive Users Check Script

directorcia edited this page Sep 30, 2025 · 2 revisions

Overview

The m365-inactiveusers-get.ps1 script is a comprehensive PowerShell tool designed to analyze user activity within Microsoft 365 tenants. It identifies inactive users, tracks license assignments, monitors external/guest user access, and generates detailed reports to help administrators maintain security and optimize license usage.

Features

๐Ÿ” User Activity Analysis

  • Identifies users who haven't signed in for a specified number of days (default: 90 days)
  • Tracks users who have never logged in
  • Monitors external/guest user activity
  • Categorizes users by activity status (Active, Inactive, Never Logged On)

๐Ÿ’ณ License Management

  • Detects unlicensed users
  • Shows detailed license assignment information
  • Helps identify opportunities for license optimization

๐Ÿ“Š Comprehensive Reporting

  • HTML Dashboard: Interactive web-based report with visual statistics
  • CSV Export: Detailed data export for further analysis
  • Console Output: Real-time progress and summary statistics
  • Search Functionality: Filter users in HTML report

๐ŸŒ External User Monitoring

  • Tracks guest/external user last login times
  • Monitors external collaborator access patterns
  • Identifies unused external accounts

Prerequisites

System Requirements

  • PowerShell: Version 5.1 or later
  • Operating System: Windows 10/11, Windows Server 2016+

Required Modules

  • Microsoft.Graph.Authentication
  • Microsoft.Graph.Users
  • Microsoft.Graph.Reports

The script will automatically install missing modules if needed.

Required Permissions

The following Microsoft Graph API scopes are required:

  • User.Read.All - Read all user profiles
  • Directory.Read.All - Read directory data
  • AuditLog.Read.All - Read audit log data
  • Reports.Read.All - Read usage reports

Installation

  1. Download the Script

    # Download from GitHub repository
    Invoke-WebRequest -Uri "https://raw.githubusercontent.com/directorcia/ciaops/master/check-inactive-users.ps1" -OutFile "check-inactive-users.ps1"
  2. Set Execution Policy (if needed)

    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Usage

Basic Execution

# Run with default settings (90-day threshold, includes guests, generates HTML report)
.\check-inactive-users.ps1

Common Usage Examples

Custom Inactive Threshold

# Check for users inactive for 30 days
.\check-inactive-users.ps1 -InactiveDays 30

Exclude External Users

# Run analysis without guest/external users
.\check-inactive-users.ps1 -IncludeGuests:$false

Silent Mode (No Browser Auto-Open)

# Generate reports but don't open browser automatically
.\check-inactive-users.ps1 -OpenReportInBrowser:$false

Debug Mode

# Enable detailed logging and transcript recording
.\check-inactive-users.ps1 -DebugMode

Generate Only CSV (No HTML)

# Generate only CSV export without HTML report
.\check-inactive-users.ps1 -GenerateHtmlReport:$false

Advanced Examples

Security Audit (Strict Settings)

# 30-day threshold, exclude guests, silent mode
.\check-inactive-users.ps1 -InactiveDays 30 -IncludeGuests:$false -OpenReportInBrowser:$false

Complete Analysis with Debug

# Full analysis with debug logging for troubleshooting
.\check-inactive-users.ps1 -DebugMode -InactiveDays 60

Parameters

Parameter Type Default Description
DebugMode Switch $false Enable detailed logging and transcript recording
InactiveDays Integer 90 Number of days to consider a user inactive (1-365)
IncludeGuests Switch $true Include guest/external users in the analysis
GenerateHtmlReport Switch $true Generate interactive HTML dashboard report
OpenReportInBrowser Switch $true Automatically open HTML report in default browser

Output Files

Generated Reports

The script creates timestamped files in the parent directory (../):

HTML Report

  • Filename: inactive-users-report-YYYY-MM-DD-HHMM.html
  • Content: Interactive dashboard with:
    • Visual statistics cards
    • Searchable user tables
    • Color-coded status indicators
    • Categorized user sections

CSV Export

  • Filename: inactive-users-YYYY-MM-DD-HHMM.csv
  • Content: Detailed data export with columns:
    • DisplayName
    • UserPrincipalName
    • UserType (Member/Guest)
    • AccountEnabled
    • ActivityStatus
    • LastSignIn
    • DaysSinceLastSignIn
    • IsUnlicensed
    • Licenses
    • CreatedDate

Log File

  • Filename: check-inactive-users-YYYY-MM-DD-HHMM.txt
  • Content: Detailed execution log with timestamps
  • Debug Transcript: Additional file when DebugMode is enabled

Report Sections

HTML Dashboard Categories

๐Ÿ“Š Statistics Overview

  • Active Users: Users who signed in within the threshold period
  • Inactive Users: Users who haven't signed in for X days
  • Never Logged In: Users who have never accessed the system
  • Unlicensed Users: Users without any license assignments
  • External/Guest Users: External collaborators and their access patterns
  • Total Users: Complete user count

๐Ÿ“‹ Detailed User Tables

Each category includes comprehensive user information:

  • Full name and email address
  • Last sign-in date and time
  • Days since last activity
  • License status and assignments
  • Account status (enabled/disabled)
  • User type (member/guest)
  • Account creation date

Security Considerations

Data Handling

  • No Sensitive Data Storage: Script doesn't store passwords or tokens
  • Temporary Files: All generated files contain user metadata only
  • Local Processing: All analysis performed locally

Permissions

  • Least Privilege: Requests only necessary Graph API permissions
  • Read-Only Access: Script only reads data, never modifies user accounts
  • Audit Trail: All activities logged for compliance

Privacy

  • License Information: Shows license types but not detailed entitlements
  • Activity Data: Limited to last sign-in dates, no browsing history
  • External Users: Tracks access patterns for security monitoring

Troubleshooting

Common Issues

Graph Module Conflicts

# Clear existing Graph modules
Get-Module Microsoft.Graph* | Remove-Module -Force

# Re-run the script
.\check-inactive-users.ps1

Permission Errors

# Connect with admin account first
Connect-MgGraph -Scopes "User.Read.All","Directory.Read.All" -TenantId "your-tenant-id"

# Then run the script
.\check-inactive-users.ps1

Large Tenant Performance

# For tenants with many users, exclude guests to improve performance
.\check-inactive-users.ps1 -IncludeGuests:$false

Debug Information

When DebugMode is enabled, the script provides:

  • Detailed module loading information
  • API request/response logging
  • Individual user processing details
  • Performance timing information

Use Cases

๐Ÿ” Security Auditing

  • Identify dormant accounts that may pose security risks
  • Monitor external user access patterns
  • Track accounts that have never been used

๐Ÿ’ฐ License Optimization

  • Find unused licenses that can be reclaimed
  • Identify users who may not need premium licenses
  • Optimize subscription costs

๐Ÿ“‹ Compliance Reporting

  • Generate regular user activity reports
  • Document user access patterns for audits
  • Maintain records of external collaborator activity

๐Ÿ”ง Administrative Maintenance

  • Clean up inactive accounts
  • Monitor onboarding effectiveness
  • Track user adoption patterns

Integration

Scheduled Execution

# Create scheduled task for weekly reports
$Action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\Scripts\check-inactive-users.ps1 -OpenReportInBrowser:`$false"
$Trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At 9AM
Register-ScheduledTask -TaskName "M365 Inactive Users Report" -Action $Action -Trigger $Trigger

PowerShell Automation

# Integrate into larger automation workflows
$Results = .\check-inactive-users.ps1 -GenerateHtmlReport:$false -OpenReportInBrowser:$false

# Process results programmatically
$InactiveUsers = Import-Csv "..\inactive-users-*.csv" | Where-Object { $_.ActivityStatus -eq "Inactive" }

Version History

Current Version Features

  • โœ… Comprehensive user activity analysis
  • โœ… Interactive HTML dashboard
  • โœ… External/guest user monitoring
  • โœ… License assignment tracking
  • โœ… Automatic browser opening
  • โœ… Debug and logging capabilities
  • โœ… CSV export functionality
  • โœ… Configurable thresholds

Support

Getting Help

  • GitHub Issues: Report bugs or request features
  • Documentation: Refer to this guide for detailed usage
  • Community: PowerShell and Microsoft 365 communities

Contributing

  • Fork the repository
  • Create feature branches
  • Submit pull requests
  • Follow PowerShell best practices

License

This script is provided as-is under the MIT License. Use at your own risk. No guarantees or warranty provided.


Generated by: CIAOPS Inactive Users Check Script
Author: Anthony Fontanez
Website: www.ciaops.com
Repository: https://github.com/directorcia/ciaops

Clone this wiki locally