HomeNewsletterCommunityMVP FeedToolsArchiveBlogToday's NewsAboutServicesQuick Links★ Pro Subscribe free
← Back to Blog
Windows Hello for Business Windows Hello for BusinessPRTIntune RemediationsdsregcmdAADSTS130004Entra ID

Windows Hello and PRT remediations: what is safe to automate and what never is

IA
Imran Awan
31 October 2026

On one enterprise laptop, Windows Hello sign-in failed with a message that a PRT refresh usually fixes. We had a remediation for exactly that message. It runs dsregcmd /refreshprt. On this laptop it would have run on every cycle, exited cleanly every time, and fixed nothing.

The script was not broken. The gap was that nobody had asked which failures a PRT refresh can fix and which it never can. This post gives you five classes to sort every Windows Hello for Business (WHfB) and Primary Refresh Token (PRT) "fix" into before it goes near an unattended remediation.

The short version

Sort every repair into one of five classes: report only, safe to automate, conditionally automatable, change-controlled, or prohibited for broad unattended use. Clearing the TPM, deleting the Ngc folder, certutil -deletehellocontainer, purging Web Account Manager caches, dsregcmd /leave, and deleting Entra devices or authentication methods all destroy state a script cannot give back. A PRT refresh is the subtle one. It helps after a network blip and loops forever when Entra has no Hello key for the user (AADSTS130004). Read the PRT diagnostics first, stop on any AADSTS server error, and make every remediation print a classification and its evidence before it changes anything.

The problem: a repair that exits cleanly and fixes nothing

The user saw "credentials could not be verified" at the Hello prompt. Every device check passed: Hello was set up, the device keys passed their test and the device was joined. On other laptops I have seen the same message with a harmless cause. The network was not ready at sign-in, and a retry a few seconds later worked. That is the case the refresh remediation was written for.

The answer was in the SSO State section of dsregcmd /status, run as the user. This is its shape, with the values changed:

Command Prompt - dsregcmd /status as the user, SSO State (illustrative)
dsregcmd /status +----------------------------------------------------------------------+ | SSO State | +----------------------------------------------------------------------+ AzureAdPrt : YES AzureAdPrtUpdateTime : 2026-10-21 11:18:04.000 UTC RefreshPrtDiagnostics : PRESENT Previous Prt Attempt : 2026-10-27 07:28:27.000 UTC User Identity : user@contoso.com Credential Type : NGC HTTP Error : 0x0 HTTP status : 400 Server Error Description : AADSTS130004: UserPrincipal doesn't have the NGC key configured.

Illustrative. Layout and field names follow Microsoft's dsregcmd documentation. Dates and UPN are invented.

So the key exists on the laptop, and Entra has no matching key for the user. Nothing on the device can change that. A refresh sends the same key to the same service and gets the same answer. The next detection finds the same problem, and the loop never ends on its own. The companion post, AADSTS130004: the Hello key is missing in Entra, covers proving the cause and the repair.

📋 Note: /refreshprt only asks. Microsoft's documented output is "PRT refresh scheduled. Check AAD event logs for details." The same article says "Wait one to two minutes for the token refresh to occur." The command returns before the refresh happens, so a remediation that runs it and exits 0 has proved nothing.

Why it happens: an exit code is not a diagnosis

An Intune remediation is two scripts. Microsoft's rule: "A remediation script only runs if the detection script uses exit code exit 1, meaning the issue was detected." Then the package runs again on its schedule, which can be hourly. And "If a scheduled run is missed, the remediation runs when the device is online, and as soon as possible."

So if detection says "broken" and the repair cannot fix it, the repair runs on every cycle for as long as the package is assigned. A harmless repair in that loop hides the real fault behind rows of "remediated". A destructive repair does damage on every cycle.

detection exits 1→repair runs→fault was never local→next cycle: same detection, same repair

Two failures that look the same on the device

Microsoft's PRT troubleshooting article sorts renewal errors into "Common server error codes ("AADSTS" prefix)" and "Common network error codes ("ERROR_WINHTTP_" prefix)". They need opposite handling.

Network blipServer rejection
What dsregcmd showsA non-zero HTTP Error. No AADSTS code.HTTP Error : 0x0, an HTTP status, and an AADSTS code in Server Error Description.
Does a retry help?Often.No. Same request, same answer.
Class for /refreshprtConditionally automatableReport only. Hand it to a person.

Windows also renews the PRT by itself. Microsoft says "The Cloud Authentication Provider (CloudAP) plug-in renews the PRT every four hours." After a blip, the next normal renewal does the work anyway. A scripted refresh only speeds it up.

What each "fix" actually destroys

ActionWhat Microsoft says it removes or changesWho it hits
Clear-Tpm"A reset removes the owner authorization value and any keys stored in the TPM." The WMI method's page adds: "By clearing the TPM, you will lose all TPM keys created and used by applications."Every user and every TPM-backed key on the device, Hello keys included.
Deleting or taking ownership of the Ngc folderNot documented as something to delete. Microsoft's FAQ gives one supported way to remove a Hello container, and it is certutil, not the file system.Everyone who enrolled on the device.
certutil -deletehellocontainerDeletes the Hello for Business container. On the latest Windows 11 it "clears not only Windows Hello for Business, but also any passkeys stored on that Windows device."The account that runs it. There is no documented switch to target another user.
Purging Web Account Manager (WAM) or token broker cachesWAM "is the default token broker on Windows 10 or newer devices." I found no Microsoft page that documents deleting its caches as a supported repair.Apps that get their tokens through the broker.
dsregcmd /leaveRemoves the device registration. Microsoft documents dsregcmd.exe /debug /leave for unjoining a hybrid joined device, after automatic registration is turned off: "Then the scheduled task doesn't register the device again."Every user. The registration belongs to the device.
Deleting the Entra device"Removes all details attached to the device." "For example, BitLocker keys for Windows devices." "Is a nonrecoverable activity."The device, its users, and its stored BitLocker recovery keys.
Deleting a WHfB authentication methodGraph's DELETE .../authentication/windowsHelloForBusinessMethods/{id} "Deletes a windowsHelloForBusinessAuthenticationMethod object." Its device property is "The registered device on which this Windows Hello for Business key resides."That user's Hello key for that device, on the Entra side.

The TPM and BitLocker. Microsoft's WHfB FAQ says "the PIN is user-provided entropy used to load the private key in the Trusted Platform Module (TPM)." Clear the TPM and every user's Hello key goes with it. The BitLocker consequence is on the WMI Clear page: "This method suspends BitLocker if calling could cause BitLocker recovery to be required." It also says "If these keys were used to encrypt data, ensure that you have another way to access the data before clearing the TPM." A remediation cannot make sure of that.

The Ngc folder. It lives at C:\Windows\ServiceProfiles\LocalService\AppData\Local\Microsoft\Ngc, a service profile shared by the whole device. Microsoft says "The maximum number of supported enrollments on a single device is 10", and "Windows prevents users on the same device from enumerating provisioned Windows Hello for Business credentials for other users." One device can hold several people's credentials. Emptying the folder removes all of them, and taking ownership changes its permissions too.

Entra joined devices. Unjoining one is worse than a hybrid unjoin. Microsoft's guidance is to "make sure you have an offline local administrator account or create one", because afterwards "You can't sign in with any Microsoft Entra user credentials."

⚠ Warning: these are not repairs. Clear-Tpm, deleting the Ngc folder, purging WAM caches, dsregcmd /leave, and deleting Entra devices or authentication methods destroy state a script cannot restore. Never put them in an Intune remediation that runs unattended on a group. When a person decides one is needed on one device, first check the BitLocker recovery key is escrowed, a local administrator exists, and the user is present.

How to verify: classify the device before anything changes

Every check here only reads. The goal is one named state per device, with the evidence that put it there.

Step 1: read dsregcmd in the right context

For the SSO State section, Microsoft says "The command must run in a user context to retrieve that user's valid status." So a remediation that reads Hello or PRT state needs Run this script using the logged-on credentials set to Yes. Microsoft's guidance for that setting is "This setting is dependent on the script."

The fields that matter, with Microsoft's definitions:

⚠ Gotcha: the diagnostics can belong to someone else, or be gone. Microsoft says they are shown "only if the acquisition or refresh failure happened after the last successful PRT update time". And: "On a shared device, this diagnostics information could be from a different user's login attempt." Compare User Identity with the signed-in user before acting. An empty block only means no failure was recorded since the last success.

Step 2: name the state

The rules are mine. The fields they read are Microsoft's. First match wins.

StateRuleWhat may run
NeedsManualInvestigationNot joined, DeviceAuthStatus starts with FAILED, or the diagnostics belong to another user.Nothing. A person checks the device object and the join.
TPMFailureAadRecoveryEnabled : YES.Nothing scripted. Microsoft: "The next sign-in will trigger the recovery flow and re-register the device."
PRTFailure, server errorServer Error Description holds an AADSTS code.Nothing on the device. Look up the code.
PRTFailure, no server errorAzureAdPrt is not YES, no AADSTS code.One guarded dsregcmd /refreshprt.
HealthyNgcSet : YES.Nothing.
PolicyBlockedNgcSet : NO and PolicyEnabled : NO.Fix the policy at its source.
LocalKeyFailureNgcSet : NO, PRT present, policy on or not reported.Nothing unattended. A person checks whether the user has simply not enrolled.

For PolicyBlocked, the setting is Use Windows Hello for Business: "If you disable this policy setting, the device doesn't provision Windows Hello for Business for any user".

Step 3: a detection script that classifies and changes nothing

This script applies the rules and prints one line: the state, then the evidence. It writes nothing. Deploy it alone first. Microsoft allows that: "A script package can contain a detection script only or both a detection script and a remediation script."

Detect-HelloState.ps1 - detection only, run as the logged-on user, writes nothing
# Read-only. User State and SSO State need the user context. $raw = dsregcmd /status function Get-DsregField { param([string]$Name) $pattern = '^\s*' + [regex]::Escape($Name) + '\s*:' $line = $raw | Where-Object { $_ -match $pattern } | Select-Object -First 1 if ($null -eq $line) { return '' } return ($line -split ':', 2)[1].Trim() } # First match of each field. AzureAdPrt diagnostics print before EnterprisePrt. $e = [ordered]@{ AzureAdJoined = Get-DsregField 'AzureAdJoined' DeviceAuth = Get-DsregField 'DeviceAuthStatus' AadRecovery = Get-DsregField 'AadRecoveryEnabled' NgcSet = Get-DsregField 'NgcSet' PolicyEnabled = Get-DsregField 'PolicyEnabled' AzureAdPrt = Get-DsregField 'AzureAdPrt' PrtUpdated = Get-DsregField 'AzureAdPrtUpdateTime' PrtUser = Get-DsregField 'User Identity' HttpError = Get-DsregField 'HTTP Error' ServerError = Get-DsregField 'Server Error Description' } $aadsts = '' if ($e.ServerError -match 'AADSTS\d+') { $aadsts = $Matches[0] } if ($e.AzureAdJoined -ne 'YES' -or $e.DeviceAuth -like 'FAILED*') { $state = 'NeedsManualInvestigation' } elseif ($e.AadRecovery -eq 'YES') { $state = 'TPMFailure' } elseif ($aadsts) { $state = 'PRTFailure' # server said no: never retry } elseif ($e.AzureAdPrt -ne 'YES') { $state = 'PRTFailure' # no server error recorded: may be transient } elseif ($e.NgcSet -eq 'YES') { $state = 'Healthy' } elseif ($e.PolicyEnabled -eq 'NO') { $state = 'PolicyBlocked' } else { $state = 'LocalKeyFailure' } $evidence = ($e.GetEnumerator() | ForEach-Object { '{0}={1}' -f $_.Key, $_.Value }) -join '; ' $out = "$state | aadsts=$aadsts | $evidence" if ($out.Length -gt 2000) { $out = $out.Substring(0, 2000) } Write-Output $out if ($state -eq 'Healthy') { exit 0 } exit 1

The server-error check comes before the PRT check on purpose. The diagnostics appear when a refresh failed after the last success, so AzureAdPrt can still say YES while renewals are refused. The output is capped with the state first, because "The maximum allowed output size limit is 2,048 characters."

The shared-device rule is left out to keep the snippet short. Compare PrtUser with the signed-in user's UPN before relying on it on shared devices.

The fix: five classes, and where each repair belongs

Before you write a remediation, put its action in one class. If you cannot decide which, it is not ready to automate.

ClassMeaningWHfB and PRT examples
Report onlyReads state. Changes nothing.dsregcmd /status, the classifier above, Entra sign-in and audit logs, reading a user's methods in Graph.
Safe to automateCannot destroy state. Repeating it is harmless.Writing state and evidence to the output. Asking the user to lock and unlock: Microsoft's advice for a stale PRT is "Lock and unlock the device to force a PRT refresh, and then check whether the time is updated."
Conditionally automatableSafe only after a check proves the precondition.dsregcmd /refreshprt, only with no AADSTS server error and diagnostics that belong to the signed-in user.
Change-controlledOne device or user, a named engineer, evidence recorded, user aware.certutil -deletehellocontainer for one proven user. Deleting one stale WHfB method. dsregcmd /debug /leave on one hybrid device. Deleting one Entra device after Intune retire or wipe.
Prohibited for broad unattended useNever in a remediation assigned to a group.Clear-Tpm, the Ngc folder, WAM or token broker purges, dsregcmd /leave, certutil -deletehellocontainer across many users, bulk deletion of Entra devices or methods.

certutil -deletehellocontainer appears twice on purpose. For one proven user it is a valid change. Unattended across a group it is prohibited. Microsoft says "advance preparation is required before executing the certutil -deletehellocontainer command", because of the user's passkeys. A script cannot prepare that for them.

The guard for the one repair that can run unattended

This is the conditionally automatable refresh, done safely. It reads the diagnostics first and stops on any AADSTS code. Otherwise it asks for one refresh. It never loops and never waits for a result.

Remediate-GuardedPrtRefresh.ps1 - run as the logged-on user, at most one refresh request
# Paste the Get-DsregField helper from the detection script above this line. $raw = dsregcmd /status $server = Get-DsregField 'Server Error Description' $prt = Get-DsregField 'AzureAdPrt' # The guard: a server rejection is never fixed by asking again. if ($server -match 'AADSTS\d+') { Write-Output "STOP PRTFailure server=$($Matches[0]) action=none reason=server-rejected" exit 0 } if ($prt -eq 'YES') { Write-Output "STOP action=none reason=prt-present" exit 0 } # No server error recorded: one request. The next detection judges the result. dsregcmd /refreshprt | Out-Null Write-Output "ACTION PRTFailure action=refreshprt-requested result=unknown-until-next-detection" exit 0

Good looks like: after a blip, the next detection reports Healthy or a newer PRT update time. Bad looks like: the next detection shows an AADSTS code. The guard then stops on every run and the device stays in your report with the code beside it. A person needs to look.

Devices › Manage devices › Scripts and remediations › Create script package
Detection script file: Detect-HelloState.ps1
Remediation script file: Remediate-GuardedPrtRefresh.ps1, or none for report only
Run this script using the logged-on credentials: Yes

When a destructive step really is needed

AADSTS130004 is one such state. The repair in the companion post deletes that user's Hello container so they can enrol again. That is a change-controlled job for one user, not a remediation.

⚠ Destructive manual step: certutil -deletehellocontainer. Microsoft: "You can delete the Windows Hello for Business container by executing the command certutil.exe -deleteHelloContainer." On the latest Windows 11 it also clears any passkeys stored on that device. Before running it, prove the cause, ask the user about passkeys, and confirm they can sign in with a password. Run it in the user's own session, not elevated, with the user present.

Two settings make destructive steps rarer:

✅ Tip: ship the classifier before any repair. Assign Detect-HelloState.ps1 alone for a week. Export the output and count the states. You will see how many devices sit in PRTFailure with a server code, which no device-side repair can fix, before you change a single device.

Proof it worked: evidence in the report, not just a green tick

Open the package under Devices › Manage devices › Scripts and remediations and select Device status. Microsoft suggests you "use the Export option to save the output as a .csv file". Each row now carries a state and its evidence.

Detection and remediation output, two devices over two days (illustrative)
# DESKTOP-A1B2C3: network blip on day 1, healthy on day 2 PRTFailure | aadsts= | AzureAdJoined=YES; ...; AzureAdPrt=NO; HttpError=(non-zero); ServerError= ACTION PRTFailure action=refreshprt-requested result=unknown-until-next-detection Healthy | aadsts= | AzureAdJoined=YES; ...; NgcSet=YES; AzureAdPrt=YES; HttpError=; ServerError= # DESKTOP-D4E5F6: Entra has no Hello key for the user. The guard stops every time. PRTFailure | aadsts=AADSTS130004 | AzureAdJoined=YES; ...; HttpError=0x0; ServerError=AADSTS130004: ... STOP PRTFailure server=AADSTS130004 action=none reason=server-rejected PRTFailure | aadsts=AADSTS130004 | AzureAdJoined=YES; ...; HttpError=0x0; ServerError=AADSTS130004: ...

Illustrative. Device names are invented and evidence is shortened with "...".

Then check every package you already run. If a remediation script contains an action from the prohibited row, remove the action, keep the detection, and route the evidence to a person.

References

Related reading on EndpointWeekly

The opening case is from one enterprise laptop. All command output is illustrative, with invented values. Microsoft facts were checked against the pages above on 31 October 2026.

Was this post helpful?
React below — no account needed
Share this post
LinkedIn X / Twitter Reddit Bluesky

More from EndpointWeekly

Windows Hello for Business
WHfB "Your credentials could not be verified": two causes, one…
One Hello sign-in error, two unrelated causes: a network that is not ready yet, or a key…
Windows Hello for Business
AADSTS130004: the Hello key works on the laptop but is missing…
Every device check passes, yet Hello sign-in fails days later with AADSTS130004. Why…
Windows Hello for Business
Check Windows Hello for Business Keys in Entra ID With Microsoft…
NgcSet : YES only proves the laptop has a Hello key. Read the cloud half with Microsoft…