I recently faced a challenge that many IT administrators are dealing with: Microsoft's deprecation of SMS-based multi-factor authentication. While SMS has served us well for years, it's now considered a weak authentication method vulnerable to SIM swapping and interception attacks. The real complexity isn't just finding who uses SMS - it's identifying who only has SMS without any stronger alternatives.
Having already built an interactive Microsoft Authenticator setup guide and implemented IIS logging to track who's accessing it, I needed to close the loop: identify users still relying solely on SMS and notify them to upgrade their authentication methods.
Visual Results
This shows the e-mail that users receive who are using SMS notifications as the only valid login method:
The Challenge
The IIS logs tell me who's visiting the Authenticator setup page, but that's only part of the story. I needed to know:
- Which visitors still have SMS authentication enabled?
- More importantly, who has only SMS with no stronger alternatives?
- How can I automatically notify just those users who need to take action?
This led me to develop a two-script solution that bridges the gap between web analytics and identity management.
Script 1: Authentication Method Analysis
The first script reads the CSV output from my IIS log analysis and enriches it with actual authentication method data from Microsoft Graph API.
Prerequisites
Before running the script, I needed to set up an App Registration in Azure AD with these specific Graph API permissions:
UserAuthenticationMethod.Read.All(Application permission)User.Read.All(Application permission)
These allow the script to query authentication methods for any user without requiring delegated permissions.
How It Works
The script takes the IIS log CSV which looks like this:
Username,UPN,TotalHits,UniqueURLs,URLCount,FirstAccess
BEAR\Lee,Lee@croucher.cloud,10,/Authenticator/,1,2026-01-09 10:56:21
And enriches it with authentication method data:
# Key function that queries Graph API for each user's auth methods
function Get-UserAuthMethods {
param (
[string]$UserPrincipalName,
[string]$Token
)
$uri = "https://graph.microsoft.com/v1.0/users/$UserPrincipalName/authentication/methods"
$response = Invoke-RestMethod -Uri $uri -Headers $headers -Method GET
The script identifies all authentication methods for each user:
- SMS Phone
- Microsoft Authenticator App
- FIDO2 Security Keys
- Windows Hello for Business
- Voice Calls
- Software OATH Tokens
The Critical Logic
Initially, I thought I just needed to find users with SMS enabled. But that would have included users who have SMS plus stronger methods. The real insight came when I realized I needed to categorize users into three groups:
$mfaStatus = if ($strongerMethods.Count -gt 0) {
if ($hasSMS) {
"Has Stronger Methods + SMS (SMS can be removed)" # Has alternatives
}
else {
"Stronger Methods Only (✓ SMS-free)" # Already migrated
}
}
elseif ($hasSMS) {
"SMS Only (⚠ Needs Stronger Method)" # These users need help!
}
The output CSV includes crucial columns:
HasSMS- Boolean flag for SMS presenceStrongerMethods- Lists all non-SMS methods (or "None")MFAStatus- Human-readable status
Script 2: Targeted Email Notifications
The second script reads the enriched CSV and sends notifications only to users who have SMS as their sole authentication method.
The Filtering Logic
This is where the earlier categorization pays off. The script filters for a very specific condition:
# Filter for users who have SMS (TRUE) AND no stronger methods (None)
$smsOnlyUsers = $allUsers | Where-Object {
$_.HasSMS -eq "TRUE" -and
($_.StrongerMethods -eq "None" -or [string]::IsNullOrWhiteSpace($_.StrongerMethods))
}
Without the StrongerMethods check, I would have unnecessarily emailed users who already have the Authenticator app installed but haven't removed SMS yet. These users are lower priority - they won't lose access when SMS is disabled.
Email Delivery
The script sends professional HTML emails through our internal SMTP server:
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort)
$smtp.EnableSsl = $false
$smtp.UseDefaultCredentials = $true
Each email:
- Clearly states the user has only SMS authentication
- Links to the setup guide
- Warns that reminder emails will continue until action is taken
- Uses Outlook-compatible HTML with proper MSO tags
Test Mode Safety
I built in a test mode to prevent accidental mass emails:
$TestMode = $true # All emails go to me for review
$TestRecipient = "lee@croucher.cloud"
In test mode:
- All emails route to my inbox
- Each email shows the intended recipient's details
- I can verify formatting and content before going live
Key Learnings
The Importance of Precise Filtering
My initial approach would have emailed 123 users (everyone with SMS enabled). The refined logic targets only the 34 users who actually need immediate help. This precision:
- Reduces helpdesk calls from confused users
- Focuses resources on those truly at risk
- Improves email engagement rates
Graph API Insights
The Graph API returns different authentication method types with specific schemas:
"#microsoft.graph.phoneAuthenticationMethod" {
if ($method.phoneType -eq "mobile") {
$methods += "SMS Phone" # This is what we're looking for
}
elseif ($method.phoneType -eq "office") {
$methods += "Voice Call" # Still stronger than SMS!
}
}
Even voice calls are considered stronger than SMS since they're harder to intercept at scale.
Email Delivery Considerations
I implemented several features for reliable delivery:
- Rate limiting (500ms delay between emails)
- Batch processing (50 emails per run)
- High priority headers for Outlook
- Comprehensive logging for audit trails
Conclusion
This two-script solution transformed a complex authentication migration from a manual nightmare into an automated, targeted process. By combining IIS analytics with Graph API data, I can identify exactly who needs help and provide it proactively.
The key insight was recognizing that not all SMS users are equal - those with alternative methods can wait, while SMS-only users need immediate attention. This targeted approach reduces noise, improves user experience, and ensures no one loses access when SMS authentication is finally disabled.
The scripts are now scheduled to run weekly, automatically identifying and notifying new SMS-only users until our environment is fully migrated to stronger authentication methods. Each run provides clear metrics on our progress toward a more secure authentication landscape.