A user tells you Windows Hello stopped working. You remote onto the device, run dsregcmd /status, and read the line everyone reads: NgcSet : YES. Hello is provisioned. The device is joined. You close the ticket.
Three days later the same user raises the same ticket, because they are still typing a password every morning. NgcSet : YES was true the whole time. It was also irrelevant. That one line tells you a key was created at some point in the past. It does not tell you the key still exists on disk, that the service which signs with it is running, that the token it feeds is valid, or that the person has used it once this month. Those are five different components, and each one reports its health somewhere else.
Windows Hello for Business health is spread across eight surfaces: dsregcmd, the TPM, the NGC container folder, the device registration certificate, PassportForWork policy, four Windows services, three event logs, and the audit configuration. Checking one of them and stopping is the most common triage mistake, and NgcSet : YES is the line that causes it. This post walks every surface, explains what each one actually proves, and gives you a read-only PowerShell collector plus a single-file offline viewer so one device can be triaged in about a minute instead of forty. Both are on GitHub, both are free, and the viewer never sends anything anywhere.
The problem: the 60-second check that lies to you
Here is the output almost everyone stops at. On the face of it, this device is perfectly healthy. It is joined, Hello is provisioned, and the security chip is protecting the key.
+----------------------------------------------------------------------+
| Device State |
+----------------------------------------------------------------------+
AzureAdJoined : YES
EnterpriseJoined : NO
DomainJoined : YES
+----------------------------------------------------------------------+
| User State |
+----------------------------------------------------------------------+
NgcSet : YES
NgcKeyId : {aaaaaaaa-0b0b-1c1c-2d2d-333333333333}
WorkplaceJoined : NO
WamDefaultSet : YESNow here is the same device, read properly. Four of these values are the reason the user is still typing a password, and not one of them appears in the block above.
NgcSet : YES <- the line that closed the ticket NGC containers on disk : 0 <- there is no key to sign with KeySignTest : FAILED <- Windows own test of that key AzureAdPrt : NO <- no single sign-on token NgcSvc : Stopped <- the service that runs Hello Sign-ins, last 30 days : Password 41, PIN 0, Fingerprint 0 Device certificate : Expired 2026-09-30
This is not a contrived example. These states are routine, and they are independent of each other. A device can hold a perfectly valid Hello key and still have no token. It can have a healthy token and a cleared TPM. It can pass every structural check and have a user who has not touched the fingerprint reader since the day it was enrolled.
The three combinations that cause most repeat tickets:
NgcSet : YESwith zero NGC containers. The registry says Hello is set up for this user. The folder that holds the protected key is empty. Windows will offer the PIN prompt and then fail to sign with it. This is the state that most often follows a TPM clear or a firmware update.NgcSet : YESand a healthy key, butAzureAdPrt : NO. Hello itself is fine. The single sign-on token is gone, so every Microsoft app prompts for credentials all day. Users describe this as “Hello is broken” because the symptom they feel is constant prompting.- Everything structurally green, and the sign-in history is 100% password. Nothing is broken. The user was never shown how to use the fingerprint reader, or it failed once and they gave up. No diagnostic script will ever flag this as a fault, and it is the single biggest gap between the adoption number on your dashboard and reality.
NgcSet is a state read, not a functional test. The functional test is KeySignTest, which asks the key to actually sign something. A device can report NgcSet : YES and KeySignTest : FAILED at the same time, and only the second one tells you whether the user can get to their desktop.Why it happens: Hello is a chain, not a switch
Windows Hello for Business is often described as if it were a feature you turn on. It is closer to a chain of seven dependencies, and the user experience is determined by the weakest link. Break any one and the symptom is identical: a password prompt.
- A cloud identity. The device must be registered with Entra ID. No registration, no Hello.
- Policy. Something has to tell the device to offer Hello, via Intune or Group Policy.
- A security chip. The TPM holds the private key. If it is not ready, Windows either refuses to create a key or creates a weaker software one.
- The key itself. Created once per user per device, stored in the NGC container.
- Services.
NgcSvcruns Hello andKeyIsoisolates the keys. Both must be running at the moment of sign-in. - A token. The Primary Refresh Token is what turns a successful Hello gesture into silent access to Microsoft 365.
- A human. Someone has to choose the fingerprint reader over the password box.
Each of those links reports its health through a different component, which is why no single command covers them. Worse, two of them report differently depending on who is asking.
NgcSet and AzureAdPrt are per-user values. Run dsregcmd /status as the signed-in user and you see that user's Hello key and token. Run the same command as SYSTEM, which is how Intune Proactive Remediations execute by default, and the User State block reflects the SYSTEM context instead. A detection script that reads NgcSet while running as SYSTEM is not reading the state of the person who raised the ticket. This is the most common reason a fleet report and a device both look right while the user is still stuck.Registry values worth knowing
Three of the seven links are registry-backed. These are the keys the collector reads, and what each value means when it is wrong. The shared parent key is stated once here rather than repeated in every row:
| Value name (type) | Healthy value | If wrong |
|---|---|---|
Enabled (REG_DWORD) | 1 | 0 explicitly disables Hello. Key absent means no policy has arrived, which is a different problem with a different fix. |
RequireSecurityDevice (REG_DWORD) | 1 | 0 allows a software key on a device with no usable TPM. Hello still works, but the key is far weaker than you think it is. |
UseCloudTrustForOnPremAuth (REG_DWORD) | 1 in a Cloud Kerberos trust deployment | Absent or 0 while you expect Cloud Kerberos trust means on-premises resources will not open after a Hello sign-in. |
MinimumPINLength under PINComplexity\ (REG_DWORD) | Your policy value, typically 6 | A value that disagrees with the Intune profile means two policies are fighting, usually a leftover GPO. |
AllowDomainPINLogon under ...\Policies\Microsoft\Windows\System\ (REG_DWORD) | Absent or 0 | 1 enables the convenience PIN, which is not Windows Hello for Business. Users believe they are on Hello when they are not. |
gpupdate reverts your change and the real misconfiguration stays hidden. Fix the Intune profile or the GPO that produced the value. The registry is where you read the answer, not where you set it.The event IDs that actually tell you something
Three logs carry Hello signals. The collector counts errors in all three, but these are the individual IDs worth opening by hand. The log channel is stated once above the table:
| Log and Event ID | Level | What it tells you |
|---|---|---|
| HelloForBusiness 7060 | Error | Creating the PIN recovery key failed. A device logging this repeatedly is warning you about a PIN lockout before it happens. Seen paired with 0x80072EE7 when the network was not up at sign-in. |
| HelloForBusiness 8060 | Information | The same operation succeeded. Use it as the paired success signal for 7060 rather than assuming silence means healthy. |
| HelloForBusiness 5702 | Information | Hello wrote its protector properties. The message names which protectors exist: PIN, Bio, Secure Bio and Recovery. A sudden change here follows a re-enrolment. |
| Biometrics 1004 | Information | A biometric identified the user, and the message names the sensor. This is the ground truth for “did they actually use the fingerprint reader?” |
| Biometrics 1605 / 1606 | Information | The secure component authorised, then redeemed, that authorisation. 1004 without 1606 means the match happened but was not used to sign in. |
| User Device Registration 360 | Warning | Provisioning was evaluated and blocked, with a per-prerequisite list in the message body. |
| User Device Registration 334 | Warning | The device could not be joined because no domain controller could be located. On a remote device this is usually the network, not the join. |
| Security 4624 type 2 / type 11 | Information | An interactive sign-in (2) or a cached one (11). Type 11 at a boot where the network came up afterwards is normal, not a failure. |
| Security 4625 | Error | A genuine failed sign-in. Sub-status 0xC0090022 means the stored Hello key could not be used at that moment. |
If you want the full decode of Event 360 and every prerequisite it reports, that is covered separately in Event ID 360: every prerequisite that blocks WHfB provisioning.
How to verify: three lines, and the context trap
Before installing anything, you can settle most tickets with one command, provided you run it in the right context. Run this as the signed-in user, not as an administrator and not as SYSTEM. An elevated PowerShell runs under a different token, and the User State block will not be the user's.
# Hello key, single sign-on token, and Windows own test that the key can sign dsregcmd /status | Select-String 'NgcSet|AzureAdPrt\s|KeySignTest' # Does a key actually exist on disk? Needs an elevated shell to read the folder. $ngc = Join-Path $env:SystemRoot 'ServiceProfiles\LocalService\AppData\Local\Microsoft\Ngc' (Get-ChildItem $ngc -ErrorAction SilentlyContinue | Measure-Object).Count # Are the two services Hello cannot work without actually running? Get-Service NgcSvc, KeyIso | Format-Table Name, Status, StartType -AutoSize
Read the result like this. NgcSet : YES with a container count of 0 is the broken state described above. KeySignTest : FAILED means stop looking anywhere else, because the key is unusable. AzureAdPrt : NO points at the token, not at Hello.
WbioSrvc and NgcCtnrSvc are trigger-started by design. They start, do their work, and stop again within seconds, so Status: Stopped on those two is the normal resting state and not a fault. Check StartType instead, and only treat NgcSvc and KeyIso showing Stopped as a real problem. Flagging the trigger-started pair is the fastest way to generate false alarms across a whole fleet.The fix: a read-only collector and an offline viewer
Three commands is fine for one device. It stops being fine when you are on a call, the user is waiting, and you need the TPM state, the certificate expiry, the policy values, the service states, the error counts and the sign-in history as well. So the three commands became a script.
Get-WHFBDeviceReport.ps1 reads all eight surfaces in one pass, scores a verdict, prints a console summary, and writes a JSON file. It is strictly read-only: it reads the registry, certificates, services, event logs, dsregcmd, Get-Tpm and auditpol, and the only thing it writes is the report itself. It changes nothing on the device, nothing in Intune and nothing in Entra ID, and it uploads nothing anywhere.
| Surface | What the script reads | What it proves |
|---|---|---|
| Identity | dsregcmd: join type, DeviceAuthStatus, device ID | Whether the device still has a valid identity to hang a Hello key on |
| Certificate | The MS-Organization-Access certificate and its expiry | Whether registration is current, or silently expired |
| Security chip | Get-Tpm: present, ready, enabled, owned | Whether a hardware-backed key is even possible |
| Hello key | NgcSet, the NGC container count, KeySignTest, KeyProvider | Whether a key exists, and whether it can still sign |
| Token | AzureAdPrt and its update and expiry times | Whether silent sign-on works, and whether renewal is running |
| Policy | The PassportForWork values in the table above | Whether policy is enabling Hello, disabling it, or absent |
| Services | NgcSvc, KeyIso, NgcCtnrSvc, WbioSrvc, TokenBroker | Whether the moving parts were running, with trigger-started services excluded from the alarm |
| Behaviour | Security 4624/4801 anchored against Hello and biometric events | How the person actually signed in, which no structural check can tell you |
Running it
Open an elevated PowerShell on the device you are troubleshooting and run the script. Without elevation it still runs, but the Security log, the TPM and the audit policy cannot be read; rather than guessing, the report lists them under “Could not be read” so you know exactly which parts are missing.
# Default run: 30 days of sign-in history, report written beside the script .\Get-WHFBDeviceReport.ps1 # Shorter window, and a specific output path .\Get-WHFBDeviceReport.ps1 -Days 7 -JsonPath C:\Temp\device.json # Masks user names, device ID, Hello key ID and certificate thumbprints. # Use this before attaching a report to a support case or a forum post. .\Get-WHFBDeviceReport.ps1 -Anonymise
-Anonymise switch exists because the moment a report leaves your team it stops being an internal document, and masking after the fact is how identifiers end up in screenshots.Reading the result
The JSON is readable on its own, but nobody wants to read JSON on a call. whfb-report-viewer.html ships beside the script: a single file with no libraries, no tracking and no network calls. Download it, open it from your own disk, and load the report. Every technical name is explained underneath it in plain English, and each value carries OK, Check or Problem as a word as well as a colour, so it reads correctly for colour-blind users and in print.
Because the parsing happens entirely in your browser, the file you open never leaves the machine. That is also why it works on an isolated device with no internet connection, which is frequently exactly where you need it.
Deploy this as an Intune Proactive Remediation
One device at a time is the right tool for a ticket. For the fleet, the same checks ship as a detection and remediation pair. The detection script runs the identical blocking checks in the identical order, so a device flagged by the fleet shows the same reason in its full report.
- Sign in to the Intune admin center.
- Go to Devices › Scripts and remediations › Remediations.
- Select Create and name it, for example “Windows Hello for Business — detect and repair”.
- On the Settings page, upload
Detect-WHFBDeviceHealth.ps1as the detection script. - Upload
Remediate-WHFBDeviceHealth.ps1as the remediation script. - Set Run this script using the logged-on credentials to No, and Run script in 64-bit PowerShell to Yes.
- Select Next, assign to a pilot group first, and set the schedule to Daily.
- Select Next › Create, then read the output column before you widen the assignment.
Read the remediation script before you deploy it, because the half that refuses to act is the important half. It will start a stopped NgcSvc or KeyIso, and it will trigger the device registration task and an MDM sync when the token or the certificate needs renewing. Those are safe, reversible and need nobody present.
It deliberately refuses four things:
- Re-enrolling Hello when
NgcSetis NO or the container is missing. The repair deletes the user's PIN and biometrics and needs them sitting at the device. Done silently at fleet scale by a scheduled task, it is indistinguishable from an attack. - Clearing a TPM that is not ready. That destroys every key on the device, BitLocker protectors included.
- Re-joining a device that is not registered. That is an enrolment decision, not a repair.
- Writing
Enabled = 1when policy set it to 0. The next sync reverts it and the real policy problem is now hidden behind a script that appears to have fixed something.
In each case it logs the reason and exits non-zero, so the device stays visible in the Intune output column instead of quietly disappearing from your problem list.
Setting the policy properly, in both worlds
If the collector reports that policy is absent or disabling Hello, fix it at the source. Both deployment paths are below, because plenty of estates still run a mix.
| Setting | Intune (Settings catalog) | Group Policy |
|---|---|---|
| Turn Hello on | Windows Hello for Business › Use Windows Hello For Business = true | Computer Configuration › Administrative Templates › Windows Components › Windows Hello for Business › Use Windows Hello for Business = Enabled |
| Require the security chip | Require Security Device = true | Same node, Use a hardware security device = Enabled |
| Cloud Kerberos trust | Use Cloud Trust For On Prem Auth = Enabled | Same node, Use cloud Kerberos trust for on-premises authentication = Enabled |
| Record sign-ins (so usage figures are real) | Policy CSP Audit/AccountLogonLogoff_AuditLogon = Success | Computer Configuration › Windows Settings › Security Settings › Advanced Audit Policy Configuration › Logon/Logoff › Audit Logon = Success |
| Record unlocks | Policy CSP Audit/AccountLogonLogoff_AuditOtherLogonLogoffEvents = Success | Same node, Audit Other Logon/Logoff Events = Success |
The last two matter more than they look. If sign-in auditing is off, the Security log has no anchors, the sign-in history in every report is empty, and the adoption figure on your dashboard is measuring nothing. The collector reports this explicitly rather than showing you a confident zero.
All four files are in Daily-Tasks/whfb-device-triage. No sign-in required. The collector and the detection script are read-only; validate everything in your own environment before you widen an assignment.
Proof it worked: what a clean device looks like
Here is the console summary from a healthy device. The verdict line is the headline, and the four lines underneath are the ones you quote back to the user.
WHfB device report - LAP-DEMO-01
----------------------------------------------------------
HEALTHY - Windows Hello for Business looks correctly set up
Join : Hybrid joined / Cloud Kerberos trust
NgcSet : YES NGC containers: 1
AzureAdPrt : YES TPM ready : True
Sign-ins : 112 anchor events for 1 user(s)
Report written: .\WHFB-Device-LAP-DEMO-01-20261012-0930.json
Open whfb-report-viewer.html and load that file to read it.And here is the same script on the device from the top of this post. Note that it separates blockers from notes: the password habit is reported, but it does not turn the verdict red, because nothing on the device is broken.
WHfB device report - LAP-DEMO-02 ---------------------------------------------------------- NEEDS ATTENTION - 4 blocking issue(s) found [blocker] Device registration certificate has expired [blocker] NgcSet says YES but there is no NGC container on disk [blocker] No single sign-on token (AzureAdPrt is not YES) [blocker] A service Windows Hello depends on is stopped [note] Windows Hello is set up but a password was still the most used sign-in method [note] Sign-in auditing is incomplete, so the usage figures above under-report Join : Hybrid joined / Key or certificate trust NgcSet : YES NGC containers: 0 AzureAdPrt : NO TPM ready : True Sign-ins : 41 anchor events for 1 user(s)
Four blockers, in priority order, from a check that took under a minute. The expired certificate is the root cause: once registration lapsed, the token could not renew, and the Hello container was never rebuilt. Renew the registration and three of the four resolve together.
In the viewer, the same report renders as a verdict panel followed by one card per surface, each value carrying its own plain-English explanation. A simulated extract:
The pattern worth taking away is not the script. It is the habit: when a user says Hello is broken, establish which of the seven links failed before you touch anything. Most of the time the answer is not the one the first command gives you.
References
- Windows Hello for Business documentation — Microsoft Learn
- Windows Hello for Business cloud Kerberos trust deployment guide — Microsoft Learn
- Troubleshoot devices by using the dsregcmd command — Microsoft Learn, the authoritative field reference for every value in this post
- What is a Primary Refresh Token? — Microsoft Learn
- Remediations in Microsoft Intune — Microsoft Learn
- PassportForWork CSP reference — Microsoft Learn