In Microsoft Entra ID, service principals are widely used by applications, integrations, and automation workflows. However, over time, many service principals may become inactive or unused.
Service principals with no sign-in activity for an extended period can indicate:
👉 Identifying such inactive service principals is crucial for:
This script helps administrators identify Entra service principals with no sign-in activity in the last 30 days and export the results for review.
Try the M365Corner Microsoft 365 Reporting Tool — your DIY pack with 20+ out-of-the-box M365 reports for Users, Groups, and Teams.
# Connect to Microsoft Graph
Connect-MgGraph -Scopes Application.Read.All, AuditLog.Read.All
Write-Host "Scanning Service Principals with NO sign-in activity (last 30 days)..." -ForegroundColor Cyan
# Define timeframe
$Days = 30
$StartDate = (Get-Date).AddDays(-$Days)
# Get all service principals
$ServicePrincipals = Get-MgServicePrincipal -All -Property Id,DisplayName,AppId,Tags
# Get sign-in logs for timeframe
$SignIns = Get-MgAuditLogSignIn -Filter "createdDateTime ge $($StartDate.ToString('yyyy-MM-ddTHH:mm:ssZ'))" -All
# Extract SP AppIds that have activity
$ActiveSPs = $SignIns |
Where-Object { $_.AppId } |
Select-Object -ExpandProperty AppId -Unique
$Results = @()
foreach ($SP in $ServicePrincipals) {
# Exclude Microsoft apps (optional but recommended)
if (
$SP.Tags -contains "WindowsAzureActiveDirectoryIntegratedApp" -or
$SP.Tags -contains "MicrosoftApplication"
) {
continue
}
# Check if SP has NO activity
if ($ActiveSPs -notcontains $SP.AppId) {
# Console output (minimal)
Write-Host "$($SP.DisplayName) | $($SP.AppId)" -ForegroundColor Yellow
# Export object
$Results += [PSCustomObject]@{
DisplayName = $SP.DisplayName
ServicePrincipalId = $SP.Id
AppId = $SP.AppId
LastSignInStatus = "No sign-in activity in last $Days days"
RiskLevel = "Review Required"
}
}
}
# Export results
$ExportPath = "C:\Path\SP_NoSignInActivity_Report.csv"
$Results | Export-Csv $ExportPath -NoTypeInformation
Write-Host "Report exported to $ExportPath" -ForegroundColor Cyan
| Step | Description |
|---|---|
| Connect to Graph | Authenticates using Application.Read.All and AuditLog.Read.All |
| Define Timeframe | Sets the last 30 days as the activity window |
| Fetch Service Principals | Retrieves all service principals |
| Fetch Sign-In Logs | Retrieves sign-in logs within the defined timeframe |
| Extract Active SPs | Collects AppIds that have recorded activity |
| Exclude Microsoft Apps | Skips Microsoft-managed service principals |
| Identify Inactive SPs | Filters service principals not found in active list |
| Build Report | Stores inactive SP details in structured format |
| Export Results | Exports report to CSV |
| Enhancement | Description |
|---|---|
| Include Last Sign-In Date | Capture actual last sign-in timestamp |
| Combine With Owner Info | Identify inactive SPs with no owners |
| Add Permission Analysis | Include permissions to assess risk |
| Extend Timeframe | Allow custom timeframe input |
| Auto Cleanup Flag | Mark candidates for deletion or review |
| Question | Answer |
|---|---|
| What does “no sign-in activity” mean? | No authentication activity recorded in the last 30 days |
| Are inactive service principals risky? | Yes, they may be unused but still hold permissions |
| Why exclude Microsoft apps? | They are system-managed and expected to behave differently |
| Can logs be incomplete? | Yes, depending on retention and licensing |
| Should inactive SPs be deleted? | Only after verifying they are no longer required |
| Use Case | Description |
|---|---|
| Security Audit | Identify unused identities |
| Cleanup Activity | Remove stale service principals |
| Governance Review | Ensure active usage of identities |
| Risk Reduction | Reduce attack surface |
| Compliance Reporting | Track identity activity and lifecycle |
| Error | Cause | Solution |
|---|---|---|
| Insufficient privileges | Missing permissions | Use Application.Read.All and AuditLog.Read.All |
| No sign-in data returned | Log retention limits | Verify audit log retention settings |
| Cmdlet not recognized | Graph module missing | Install using Install-Module Microsoft.Graph |
| Slow execution | Large log dataset | Apply additional filtering if needed |
| Empty results | No inactive SPs found | Verify timeframe or tenant activity |
Service principals with no sign-in activity over extended periods are often overlooked but can represent unused or forgotten identities with potential access to sensitive resources.
This Microsoft Graph PowerShell script provides a simple way to identify inactive service principals and export them for review. By incorporating this into regular audits, administrators can:
Regular monitoring ensures your Entra environment remains clean, secure, and well-governed.
© Created and Maintained by LEARNIT WELL SOLUTIONS. All Rights Reserved.