Your security team asks a simple question: "Today, when this user signed in — did they use face, fingerprint, PIN, or did they just type their password?" You open the Entra sign-in logs, and the answer is useless. Every Windows Hello sign-in — face, fingerprint and PIN — collapses into one label: "Windows Hello for Business." There is no gesture-level report anywhere in Intune or Entra. So I went into the Windows event logs and built one. This is exactly how it works, and where every number comes from.
The problem — Entra tells you nothing useful
Here is what the Entra sign-in logs give you under Authentication Details for a Windows Hello sign-in:
That's it. Face, fingerprint and PIN are all one label. Intune doesn't break it down either. This isn't an oversight — it's a consequence of how Windows Hello works.
Why Microsoft can't show you — the mechanism
Windows Hello for Business does not store three credentials. It stores one: an asymmetric key pair, protected by the TPM. Your PIN, fingerprint and face are not credentials — they are three gestures that all unlock the same private key.
When that key signs the authentication challenge, the wire looks identical no matter which gesture released it. So Entra correctly reports one thing for all three. A password is the odd one out — it never touches that key, which is the only reason Entra can separate "Password" from "WHfB". The gesture distinction only exists locally, on the device, at the instant the gesture unlocks the key. That's where we have to look.
First, confirm the device is what we think it is. On a hybrid cloud trust device, dsregcmd /status is the source of truth:
C:\> dsregcmd /status
AzureAdJoined : YES
DomainJoined : YES
NgcSet : YES
KeyProvider : Microsoft Platform Crypto Provider
TpmProtected : YES
OnPremTgt : YES
CloudTgt : YES
AzureAdJoined + DomainJoined = hybrid joined. OnPremTgt + CloudTgt = cloud trust. NgcSet: YES = Windows Hello is provisioned, TPM-backed. Exactly the scenario we care about.
Where the data actually lives — three event logs
There is no single "Windows Hello usage" log. The answer is scattered across three logs, and you have to stitch them together. Full paths so you can open them in Event Viewer (Applications and Services Logs › Microsoft › Windows › …):
| What it tells you | Log |
|---|---|
| Face / fingerprint was used | Biometrics / Operational |
| The Hello key was used (PIN or biometric) | HelloForBusiness / Operational |
| A sign-in / unlock happened at all | Security (Windows Logs) |
The enrollment side — what's set up — is just one registry value, a bitmask under the user's SID at HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WinBio\AccountInfo\<SID>\EnrolledFactors:
| Bit | Factor |
|---|---|
0x02 | Face |
0x04 | Voice |
0x08 | Fingerprint |
0x10 | Iris |
A value of 10 = 0x08 | 0x02 = fingerprint + face enrolled. Exact, no guessing. But enrollment is the easy half. The hard part is usage — which gesture they actually used — and that took some detective work.
The detective work — from "everything is PIN" to four clean methods
Clue 1 — Fingerprint announces itself
Every successful fingerprint match writes Event ID 1004 in the Biometrics log, and it names the sensor:
# "identified" — fingerprint, with the sensor name
The Windows Biometric Service successfully identified
[user] using sensor: Goodix MOC Fingerprint (USB\VID_27C6...).
So fingerprint = an 1004 with a fingerprint sensor name. Easy. My first version of the script used that, plus the Security log for logons, with a simple rule: "if a Hello key event is anywhere near the logon, it's PIN, else password." I gave it a generous ±90-second window to be safe. That was the mistake.
5702) fire dozens of times an hour. With a ±90s window, every sign-in had a Hello event nearby. The script reported everything as PIN. Password sign-ins vanished entirely.Clue 2 — Anchor on the real unlock, and turn on the audit
The fix was to stop guessing from loose timing and anchor on the exact moment of a sign-in. The Security log has two anchors: Event 4624 (logon — Type 2 interactive, Type 11 cached) and Event 4801 (workstation unlocked). But when I tested, the unlock events weren't there. Here's why:
C:\> auditpol /get /subcategory:"Other Logon/Logoff Events"
Logon/Logoff
Other Logon/Logoff Events No Auditing
One command, run as admin, fixes it going forward:
# Enable unlock auditing so PIN/password unlocks are recorded
auditpol /set /subcategory:"Other Logon/Logoff Events" /success:enable
Clue 3 — The face mystery
With auditing on, I locked the screen and signed in deliberately with password, then PIN, then face. The script reported PIN, Password, Password… and the face unlock came back as PIN. So I dumped every event in the window — Security, Biometrics and HelloForBusiness side by side. This cracked it:
16:13:09 Biometric 1702 "successfully unprotected data for user"
16:13:09 Biometric 1605 "secure component successfully authorized"
16:13:09 Hello 5702 Hello key protector written
16:13:09 Security 4801 workstation unlocked
(no 1004 'identified' event anywhere)
There it is. A face unlock produces Event 1702 ("unprotected data") and 1605 ("authorized") — but no 1004. Fingerprint raises 1004; face on this hardware does not. My script only looked for 1004, so face fell through, and because face also moves the Hello key (5702), it landed in the PIN bucket. Compare a PIN unlock — same Hello key, but the Biometric service stays completely silent:
16:11:17 Hello 5702 Hello key used → PIN
16:11:17 Security 4801 workstation unlocked
16:11:41 Security 4801 workstation unlocked → Password
(no Hello key, no biometric — nothing but the unlock)
The classification rules (validated on real hardware)
For every anchor (a 4624 logon or 4801 unlock), check what fired within a tight window — a few seconds, not 90:
| Method | Signal at the moment of sign-in |
|---|---|
| Fingerprint | Biometrics 1004 "identified" (names the fingerprint sensor) |
| Face | Biometrics 1702 "unprotected data" with no 1004 |
| PIN | HelloForBusiness 5702/5205 key use, but no biometric |
| Password | An unlock/logon with neither biometric nor Hello key |
1608/1019 events are just the sensor idling — ignore them.How to verify it yourself
Before trusting any script, confirm the raw signals. Run elevated:
# Every biometric sign-in today, with the sensor name
Get-WinEvent -FilterHashtable @{
LogName='Microsoft-Windows-Biometrics/Operational'; Id=1004;
StartTime=(Get-Date).Date
} | Select-Object TimeCreated, Message
The script — Get-TodayLogons.ps1
The heart of it: anchor on the Security log, classify each anchor against the biometric and Hello signals, and also add biometric sign-ins from before unlock auditing was on (so fingerprint history isn't lost).
# Fingerprint=1004 | Face=1702 w/o 1004 | PIN=Hello key only | Password=nothing
$start = (Get-Date).Date
# the three signal sources
$fp = Get-WinEvent @{LogName='...Biometrics/Operational'; Id=1004; StartTime=$start}
$faceAuth = (Get-WinEvent @{LogName='...Biometrics/Operational'; Id=1702; StartTime=$start}).TimeCreated
$hello = (Get-WinEvent @{LogName='...HelloForBusiness/Operational'; Id=5205,5702; StartTime=$start}).TimeCreated
# anchors = real unlock/logon moments from the Security log
$anchors = Get-WinEvent @{LogName='Security'; Id=4624,4801; StartTime=$start} # (filtered to user)
function Near($t,$set,$sec){ @($set | ? { [math]::Abs(($t-$_).TotalSeconds) -le $sec }).Count }
foreach($a in $anchors){
$t = $a.Time
$f = $fp | ? { [math]::Abs(($t-$_.Time).TotalSeconds) -le 8 } | select -First 1
$method = if($f){ if($f.IsFinger){'Fingerprint'}else{'Face'} }
elseif(Near $t $faceAuth 5){ 'Face' }
elseif(Near $t $hello 8){ 'PIN' }
else{ 'Password' }
}
8 and 5 second windows are the fix for the original "everything is PIN" bug. A PIN unlock fires its Hello key event at the same second as the unlock; the background noise is always tens of seconds away. Keep it tight.Proof it worked
Output after locking and unlocking with every method during testing — fingerprint history from earlier in the day, then the deliberate face / PIN / password tests, all four correctly identified with the exact time:
Date Time Method Source
---- ---- ------ ------
2026-06-29 04:33:08 Fingerprint Logon (Security log)
2026-06-29 08:00:44 Fingerprint Biometric (sign-in/unlock)
2026-06-29 10:06:27 Fingerprint Biometric (sign-in/unlock)
2026-06-29 14:07:00 Fingerprint Biometric (sign-in/unlock)
2026-06-29 15:49:34 Fingerprint Biometric (sign-in/unlock)
2026-06-29 16:10:51 Face Unlock (Security log)
2026-06-29 16:11:17 PIN Unlock (Security log)
2026-06-29 16:11:41 Password Unlock (Security log)
2026-06-29 16:12:34 Password Unlock (Security log)
2026-06-29 16:13:09 Face Unlock (Security log)
That is the report Microsoft doesn't give you: face, fingerprint, PIN and password, per sign-in, with timestamps — built entirely from data already on the device.
What's next
This was deliberately one device, run by hand. In Part 2 I'll turn this exact classifier into an Intune remediation (detection) script that runs as SYSTEM on every device and reports a single line per machine, and push the unlock-audit policy fleet-wide. Part 3 wires the collected data into a web app pulling live results through the Microsoft Graph API — a live dashboard of exactly which Hello gesture every user is really using, instead of CSV exports.
The mechanism never changes: fingerprint shouts 1004, face whispers 1702, PIN only moves the Hello key, and a password moves nothing. Once you know that, the rest is just plumbing.