WLapsAdmin or Administrator? Auditing Windows LAPS at fleet scale.
Windows LAPS (Local Administrator Password Solution) is the feature that auto-rotates
the local admin password on each PC and backs it up to Entra ID. An IT lead asked me
last week why some of his PCs showed Administrator in the LAPS recovery
portal while the rest showed WLapsAdmin. Same policy, same tenant,
identical assignments. Good question. The answer comes down to one Microsoft design
decision in Windows 11 24H2 that quietly creates a split fleet, and the only
practical way to see the full picture is via Microsoft Graph. Here is the audit I
run, end to end.
why this matters
The Intune recovery portal shows you the LAPS account name for one device at a time. There is no fleet-wide view. The Graph v1.0 list endpoint will give you device names and timestamps, but it will not give you the account name in bulk. Microsoft deliberately blocks bulk account name retrieval with an HTTP 400 error, treating password account names as sensitive metadata that should only be queried per device. On any tenant of meaningful size, the only way to see the full picture is to write the audit yourself.
On top of that, an Intune-enrolled, compliant device is not necessarily escrowing LAPS. The portal happily shows the policy as applied while the device silently fails to back up its password to Entra. The shape of a real LAPS audit on a hybrid tenant is always the same three questions:
- How many devices are actually escrowing, versus how many should be?
- For the ones that are escrowing, what account name is being managed?
- For the ones that are not, why?
before you touch anything
- Microsoft.Graph PowerShell SDK installed. Latest version, not the v1 module that Microsoft has retired. Install with
Install-Module Microsoft.Graph -Scope CurrentUser. - An admin account with the right Graph scopes. You need read access to local credentials, devices, and managed devices:
DeviceLocalCredential.ReadBasic.All,DeviceLocalCredential.Read.All,Device.Read.All, andDeviceManagementManagedDevices.Read.All. Connect once at the start of the session with all of them, so you do not get re-prompted halfway through a 90-second loop. - WAM disabled if you are on PowerShell 5.1. WAM (Web Account Manager) is the Windows broker that handles login. On PowerShell 5.1 it sometimes triggers a double prompt when
Connect-MgGraphruns. Fix: runSet-MgGraphOption -DisableLoginByWAM $truebefore connecting.
Set-MgGraphOption -DisableLoginByWAM $true
Connect-MgGraph -TenantId "00000000-0000-0000-0000-000000000000" `
-Scopes "DeviceLocalCredential.ReadBasic.All", `
"DeviceLocalCredential.Read.All", `
"Device.Read.All", `
"DeviceManagementManagedDevices.Read.All" `
-NoWelcome
step 1 · pull the escrow records
The list endpoint returns one record per escrowed device with the device name and last backup timestamp. It does not return the account name. That comes later.
$response = Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/v1.0/directory/deviceLocalCredentials"
$response.value.Count
81
Hold onto that count. The next step compares it against the live Intune inventory and almost never matches.
step 2 · pull the Intune inventory
The escrow list is one number. The Intune inventory of currently active Windows devices is another. Stale escrow records from retired devices stick around in the v1.0 list. Live devices that should be escrowing but are not get hidden by the noise. You need both.
$intune = Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices"
$winDevices = $intune.value | Where-Object { $_['operatingSystem'] -eq 'Windows' }
$winDevices.Count
84
step 3 · gap analysis
Cross-reference both lists by device name. Two outputs that you should care about: devices in Intune but not escrowing, and escrow records with no matching Intune device.
$intuneNames = $winDevices | ForEach-Object { $_['deviceName'] }
$escrowedNames = $response.value | ForEach-Object { $_['deviceName'] }
$intuneNames | Where-Object { $_ -notin $escrowedNames }
$escrowedNames | Where-Object { $_ -notin $intuneNames }
CORP-PC-014
CORP-PC-039
CORP-PC-072
(no results)
Three devices in Intune, not escrowing. No stale records on the escrow side this time. Those three are the actual investigation targets, not the headline number.
step 4 · OS eligibility, the boundary nobody talks about
Now the bit that explains the WLapsAdmin versus Administrator split. Microsoft's
Automatic Account Management feature, the one that creates and manages
WLapsAdmin instead of touching the built-in Administrator,
only applies on Windows 11 24H2 (build 10.0.26100) or later.
On Windows 11 23H2 and below, the AAM CSP settings are silently ignored and LAPS
manages the built-in Administrator under its default name. Both are correct. The
password works. The portal just shows a different account name.
$threshold = [version]"10.0.26100"
$winDevices | ForEach-Object {
[pscustomobject]@{
DeviceName = $_['deviceName']
OsVersion = $_['osVersion']
Eligible = ([version]$_['osVersion'] -ge $threshold)
}
} | Group-Object Eligible | Format-Table Name, Count
Name Count
---- -----
True 72
False 12
Twelve devices on 23H2 or below. Those will show Administrator in the
portal as long as they are on that build. They will flip to WLapsAdmin
the next time they upgrade to 24H2. No policy change required.
10.0.22621.x = 22H2. Build
10.0.22631.x = 23H2. Build 10.0.26100.x and above = 24H2.
Build 10.0.21996.x is a Windows 10 Insider Preview from October 2021,
not a production release. If a device is on that build, do not patch it. Rebuild
or replace.
step 5 · per-device account name confirmation
Now the part Microsoft will not let you shortcut. The v1.0 list endpoint does not
include accountName in its response. The natural thing to try is adding
$select=credentials to the list call to ask for it. That returns:
HTTP/1.1 400 Bad Request
{"error":{"code":"invalid_request",
"message":"Querying local account passwords over multiple devices is unsupported."}}
Why this fails: Microsoft treats local credential account names as sensitive metadata. The list endpoint will not return them in bulk by design.
Fix: a per-device foreach loop against the beta
endpoint. Around 60 to 90 seconds for 80 devices, with one Graph call per device.
The beta endpoint allows the credentials select on a single device
because it returns one record at a time.
$accountReport = foreach ($d in $response.value) {
$detail = Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/beta/directory/deviceLocalCredentials/$($d['id'])?`$select=credentials"
[pscustomobject]@{
DeviceName = $d['deviceName']
AccountName = $detail.credentials[0].accountName
}
}
$accountReport | Group-Object AccountName | Format-Table Name, Count
Name Count
---- -----
WLapsAdmin 70
Administrator 11
Seventy WLapsAdmin, eleven Administrator. The eleven match the 23H2 list from step 4 exactly. There is no policy fault. Everything is working as designed.
step 6 · the duplicate Entra object trap
For the three devices in Intune but not escrowing, the most common root cause on a
hybrid tenant is a duplicate Entra device object. A PC that has been re-imaged,
moved between domains, or had a security group reorganisation can end up with two
or three Entra objects sharing the same displayName.
Each Entra device object has a TrustType field that says how it was
joined: ServerAd (hybrid join from on-prem AD), AzureAd
(cloud-only join), or Workplace (BYOD-style registration). On a hybrid
tenant, the ServerAd object is the one that should be active. The other
two are stale leftovers.
What goes wrong: the correct ServerAd object cannot
complete its registration while stale Workplace or AzureAd
objects exist for the same name.
Why: registration writes a field called
alternativeSecurityIds on the Entra object. With duplicates blocking
the way, that field stays empty. LAPS cannot escrow without it because the device
cannot prove its identity to Entra.
Fix: identify the duplicates, confirm which is the correct
ServerAd object, then delete the stale ones via the Entra portal or
Remove-MgDevice. After cleanup, run dsregcmd /leave
followed by dsregcmd /join on the device itself to re-register cleanly.
The diagnostic is one Graph beta query per object. Pull all Entra devices with pagination first, then group by name and inspect anything with a count above 1.
$all = @()
$u = "https://graph.microsoft.com/v1.0/devices"
do {
$r = Invoke-MgGraphRequest -Method GET -Uri $u
$all += $r.value
$u = $r.'@odata.nextLink'
} while ($u)
$all | Group-Object { $_['displayName'] } | Where-Object Count -gt 1
Count Name
----- ----
3 CORP-PC-039
Three Entra objects for one device. Pull the detail on each, look for the one
with TrustType=ServerAd, and check whether its
registrationDateTime and alternativeSecurityIds are
populated. If one is empty and the other two are old Workplace or
AzureAd entries, you have found the blocker.
common gotchas
- You only see the first 100-ish devices in your "all devices" pull. A tenant with thousands of Entra objects returns one page at a time. Fix: follow
@odata.nextLinkin a loop until it stops returning. The script in the repo does this; if you copy out a fragment, do not skip the loop. Skipping pagination is the most common silent failure on this whole audit. - Escrow count is higher than expected. The v1.0 escrow list keeps records from devices that have been wiped, reprovisioned, or retired. Fix: run the gap analysis (Step 3) and quote the count of escrowed records that match a live Intune device. The raw escrow count is misleading.
- HTTP 400 on bulk credential queries. You added
$select=credentialsto the list endpoint. Fix: Microsoft blocks this by design. Do not retry. Use the per-device beta endpoint as shown in Step 5. $matching.Countreturns wildly wrong numbers. You used$matchesas a variable name.$matchesis a reserved PowerShell variable that the-matchoperator populates with regex capture groups. Fix: rename it to$deviceMatchesor anything other than$matches.- 23H2 device shows
Administratorinstead ofWLapsAdmin. Not a misconfiguration. This is by design: the WLapsAdmin account is created by a Windows 11 24H2 feature called Automatic Account Management. On 23H2 and below, LAPS just manages the built-in Administrator account and shows that name in the portal. The password works in both cases. The only "fix" is upgrading the device to 24H2.
when to skip this and just look at one device
For a one-off "why isn't this single device escrowing" question, you do not need
the fleet audit. Pull the Intune managed device record, pull the matching Entra
device object via the beta endpoint, look at registrationDateTime and
alternativeSecurityIds. Five minutes. The full audit earns its keep
when you are reporting fleet status to a customer, planning a 24H2 rollout, or
proving to compliance that 96% of the estate is escrowing as expected.