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

NgcSet Says YES and Windows Hello Still Does Not Work: Triaging One Device Properly

IA
Imran Awan
12 October 2026

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.

Watch this post on YouTube

Watch on YouTube · Subscribe at endpointweekly.com

The short version

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.

dsregcmd /status — the part everyone reads
+----------------------------------------------------------------------+
| Device State                                                         |
+----------------------------------------------------------------------+

             AzureAdJoined : YES
          EnterpriseJoined : NO
              DomainJoined : YES

+----------------------------------------------------------------------+
| User State                                                           |
+----------------------------------------------------------------------+

                    NgcSet : YES
                  NgcKeyId : {aaaaaaaa-0b0b-1c1c-2d2d-333333333333}
              WorkplaceJoined : NO
             WamDefaultSet : YES

Now 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.

The same device, eight surfaces instead of one
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:

⚠ Gotcha: 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.

  1. A cloud identity. The device must be registered with Entra ID. No registration, no Hello.
  2. Policy. Something has to tell the device to offer Hello, via Intune or Group Policy.
  3. 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.
  4. The key itself. Created once per user per device, stored in the NGC container.
  5. Services. NgcSvc runs Hello and KeyIso isolates the keys. Both must be running at the moment of sign-in.
  6. A token. The Primary Refresh Token is what turns a successful Hello gesture into silent access to Microsoft 365.
  7. 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.

📋 Note — the context trap: 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:

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\PassportForWork\
Value name (type)Healthy valueIf wrong
Enabled (REG_DWORD)10 explicitly disables Hello. Key absent means no policy has arrived, which is a different problem with a different fix.
RequireSecurityDevice (REG_DWORD)10 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 deploymentAbsent 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 6A 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 01 enables the convenience PIN, which is not Windows Hello for Business. Users believe they are on Hello when they are not.
⚠ Warning: Do not fix a wrong value by editing these keys directly. They are written by policy, so the next Intune sync or 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:

Event Viewer › Applications and Services Logs › Microsoft › Windows › HelloForBusiness | Biometrics | User Device Registration
Log and Event IDLevelWhat it tells you
HelloForBusiness 7060ErrorCreating 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 8060InformationThe same operation succeeded. Use it as the paired success signal for 7060 rather than assuming silence means healthy.
HelloForBusiness 5702InformationHello 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 1004InformationA 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 / 1606InformationThe secure component authorised, then redeemed, that authorisation. 1004 without 1606 means the match happened but was not used to sign in.
User Device Registration 360WarningProvisioning was evaluated and blocked, with a per-prerequisite list in the message body.
User Device Registration 334WarningThe 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 11InformationAn 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 4625ErrorA 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.

Run as the signed-in user — the three lines that matter
# 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.

✓ Tip: 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.

SurfaceWhat the script readsWhat it proves
Identitydsregcmd: join type, DeviceAuthStatus, device IDWhether the device still has a valid identity to hang a Hello key on
CertificateThe MS-Organization-Access certificate and its expiryWhether registration is current, or silently expired
Security chipGet-Tpm: present, ready, enabled, ownedWhether a hardware-backed key is even possible
Hello keyNgcSet, the NGC container count, KeySignTest, KeyProviderWhether a key exists, and whether it can still sign
TokenAzureAdPrt and its update and expiry timesWhether silent sign-on works, and whether renewal is running
PolicyThe PassportForWork values in the table aboveWhether policy is enabling Hello, disabling it, or absent
ServicesNgcSvc, KeyIso, NgcCtnrSvc, WbioSrvc, TokenBrokerWhether the moving parts were running, with trigger-started services excluded from the alarm
BehaviourSecurity 4624/4801 anchored against Hello and biometric eventsHow 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.

Get-WHFBDeviceReport.ps1
# 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
⚠ Gotcha: the report contains user principal names and a sign-in history for that device. It is a support capture, so treat it like one. The -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.

Run the script › WHFB-Device-NAME-DATE.json › Open whfb-report-viewer.html › Open a report file

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.

  1. Sign in to the Intune admin center.
  2. Go to Devices › Scripts and remediations › Remediations.
  3. Select Create and name it, for example “Windows Hello for Business — detect and repair”.
  4. On the Settings page, upload Detect-WHFBDeviceHealth.ps1 as the detection script.
  5. Upload Remediate-WHFBDeviceHealth.ps1 as the remediation script.
  6. Set Run this script using the logged-on credentials to No, and Run script in 64-bit PowerShell to Yes.
  7. Select Next, assign to a pilot group first, and set the schedule to Daily.
  8. Select Next › Create, then read the output column before you widen the assignment.
Devices › Scripts and remediations › Remediations › Create

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:

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.

SettingIntune (Settings catalog)Group Policy
Turn Hello onWindows Hello for Business › Use Windows Hello For Business = trueComputer Configuration › Administrative Templates › Windows Components › Windows Hello for Business › Use Windows Hello for Business = Enabled
Require the security chipRequire Security Device = trueSame node, Use a hardware security device = Enabled
Cloud Kerberos trustUse Cloud Trust For On Prem Auth = EnabledSame node, Use cloud Kerberos trust for on-premises authentication = Enabled
Record sign-ins (so usage figures are real)Policy CSP Audit/AccountLogonLogoff_AuditLogon = SuccessComputer Configuration › Windows Settings › Security Settings › Advanced Audit Policy Configuration › Logon/Logoff › Audit Logon = Success
Record unlocksPolicy CSP Audit/AccountLogonLogoff_AuditOtherLogonLogoffEvents = SuccessSame 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.

PowerShell scripts — WHfB device triage

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.

● Get-WHFBDeviceReport.ps1 — read-only collector, writes the JSON report
● whfb-report-viewer.html — offline viewer, one file, no network calls
● Detect-WHFBDeviceHealth.ps1 — Proactive Remediation detection, read-only
● Remediate-WHFBDeviceHealth.ps1 — safe repairs only, refuses the destructive ones
View all four on GitHub

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.

Console output — healthy device
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.

Console output — the device that passed the 60-second check
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:

Needs attention NEEDS ATTENTION — 4 blocking issue(s) found
NgcSet (Hello set up for this user)Whether Hello is set up for the signed-in user. NO means Hello is not active, whatever else says. YES OK
NGC containers presentThe protected key store Hello signs in with. Zero containers with NgcSet YES means there is nothing to sign with. 0 Problem
Device certificateThe certificate that proves this device is registered. Expired or missing breaks sign-in and token renewal. Expired 2026-09-30 Problem

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

Watch this post on YouTube

Watch on YouTube · Subscribe at endpointweekly.com

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

More from EndpointWeekly

Windows Hello for Business
Event ID 360: Every Prerequisite That Blocks Windows Hello for…
Event 360 in User Device Registration/Admin means WHfB provisioning will not launch.…
Windows Hello for Business
Intune Says the Hello Policy Applied. Here Is How to Prove It on…
Windows Hello for Business does not write to PolicyManager like other CSP policies, so…
Windows Hello for Business
dsregcmd /status Decoded: The Complete Field Reference for WHfB…
One command answers more WHfB questions than any portal - and its forty-plus fields come…