Identity ✓ fields verified against sample logs

Duo Security Log Format: Authentication Event Fields and Examples

Published

One record per Duo event — usually an authentication: which user was challenged, with which factor, from which device and IP, for which application, and whether the attempt was allowed, denied or reported as fraud. Administrator actions appear in the same export with a different shape.

Sample record

[{"timestamp":1705309201,"result":"ALLOW","factor":"duo_push","user":{"name":"alice","key":"DUXXXXXXXXXXXXXXXX"},"access_device":{"ip":"203.0.113.10","os":"Windows","browser":"Chrome","hostname":"DESKTOP-ALICE"},"application":{"name":"Office365 SSO"},"reason":"user_approved","event_type":"authentication"},{"timestamp":1705309262,"result":"ALLOW","factor":"totp","user":{"name":"bob","key":"DUXXXXXXXXXXXXXXXY"},"access_device":{"ip":"203.0.113.20","os":"macOS","browser":"Safari","hostname":"Bobs-MacBook"},"application":{"name":"VPN"},"reason":"valid_passcode","event_type":"authentication"},{"timestamp":1705309323,"action":"user_update","username":"admin","timestamp":1705309323,"object":"alice","description":"Updated user alias"}]

From the LogTriage parser test corpus — synthetic data, no real hosts or users.

Field reference

Field Type Meaning Why it matters for security
timestampe.g. 1705309201 Unix time (seconds) When the event was recorded, in epoch seconds. Convert before correlating with IdP, VPN or endpoint logs; the gap between consecutive pushes for one user is what separates a retry from push bombing.
event_typee.g. authentication string The kind of event the record describes. Filter on it before counting outcomes — not every object in an export is an authentication.
resulte.g. ALLOW string Outcome of the attempt. Values seen in these samples: ALLOW, DENY, FRAUD. A FRAUD record is a user-reported attempt, which is the strongest single signal in the file; an ALLOW immediately after a run of DENYs is a possible fatigue win.
factore.g. duo_push string Second factor used for the attempt. Samples contain duo_push, totp, push, sms and bypass. bypass means a bypass code was used instead of a real factor; SMS on an account that normally uses push can indicate a fallback the attacker chose.
reasone.g. user_approved string Why the attempt ended as it did. Samples contain user_approved, valid_passcode, user_marked_fraud, anomalous_push and bypass_user. The reason splits identical results apart — a DENY with anomalous_push is not the same investigation as an ordinary timeout or user denial.
user.namee.g. alice string Username of the account being authenticated. Counting distinct values per source IP finds one client working through a list of accounts.
user.keye.g. DUXXXXXXXXXXXXXXXX string Duo's stable identifier for the user object. Pivot on the key rather than the name — renaming a user changes user.name but not user.key.
access_device.ipe.g. 203.0.113.10 string IP address Duo saw the access device connect from. The main pivot for geolocation, threat intel and grouping attempts that span several accounts.
access_device.ose.g. Windows string Operating system reported for the access device. Linux on an estate of Windows laptops, or an OS that does not match the user's usual device, is worth a check.
access_device.browsere.g. Chrome string Browser or client reported for the access device. Values such as python-requests or Unknown indicate automation rather than a person at a browser.
access_device.hostnamee.g. DESKTOP-ALICE string or null Hostname reported for the access device; null when it is not available. Client-supplied, so treat it as a lead, not proof — the malicious sample carries attacker.ru in this field.
application.namee.g. Office365 SSO string Duo application (integration) the authentication was for. Tells you what the factor actually protected — VPN, SSO and Admin Panel failures have very different blast radii.
actione.g. user_update string Administrative action performed, present on administrator events instead of result and factor. Directory and user changes around the time of a suspicious authentication can be the attacker consolidating access.
usernamee.g. admin string Administrator who performed the action, on administrator events. Shows which admin account made the change; compare it with that admin's own authentication records.
objecte.g. alice string Target of the administrative action. Reveals whose enrollment, phone or alias was modified.
descriptione.g. Updated user alias string Free-text summary of the administrative change. Short and unstructured — read it, but do not build parsing logic on its wording.

What it records

Each object in a Duo export is one event. Authentication events (event_type of authentication) describe a single second-factor decision: the user (user.name, user.key), the factor attempted, the device Duo saw (access_device.ip, os, browser, hostname), the protected application (application.name), the outcome in result and the explanation in reason.

Administrator events have a different shape — action, username of the admin, object affected and a free-text description — and appear interleaved with authentications in the same array, as the last record of the benign sample shows.

Duo sits behind primary authentication, so these records are evidence about the factor, not about the password. An ALLOW on an account whose password was phished still looks ordinary unless you read the factor, the source IP and the application together.

Where to get it

  • Duo Admin Panel → Reports → Authentication Log, with CSV export for a time range. Good for one-off lookups; column names differ from the JSON field names on this page.
  • Duo Admin API. Authentication, administrator and telephony logs are separate endpoints; you need an Admin API application with log-read permission, and the returned field names match the JSON here.
  • Scheduled collection. Duo publishes an open-source log-sync utility, and most SIEMs ship a Duo collector that polls the same API endpoints — the practical route for keeping months of history.

Parsing pitfalls

  • Mixed record shapes. Authentication and administrator events share one array. Branch on event_type / the presence of action; code that assumes result exists will fail on admin records.
  • Duplicate keys. The administrator record in the benign sample contains timestamp twice. Permissive parsers keep the last value, strict ones error — check which yours does before trusting counts.
  • Nulls and missing fields. access_device.hostname is null in one malicious record and absent entirely from another; browser is Unknown in a third. Optional extras such as flash_version and java_version appear only on some records.
  • Epoch seconds. timestamp is in seconds, not milliseconds — the usual off-by-1000 error when joining with web or EDR logs.
  • Outcome vocabulary varies. These samples use ALLOW, DENY and FRAUD. Different API versions and CSV exports label the same outcomes with other strings and casing, so normalize on ingest instead of hard-coding one set.
  • Names are mutable, keys are not. Join on user.key; user.name changes when an account is renamed.

Detection ideas

  • MFA fatigue: several DENY records for one user.name within minutes, especially with reason of anomalous_push, followed by an ALLOW — the core of the Duo MFA fatigue rule.
  • User-reported fraud: any result of FRAUD or reason of user_marked_fraud. Someone pressed “this wasn’t me”, which means an attacker already had the first factor.
  • Bypass code abuse: factor of bypass with reason of bypass_user, particularly against a sensitive application.name or an administrative account. Check who issued the bypass code and when.
  • Scripted clients: access_device.browser values like python-requests, os of Linux on a Windows estate, or a missing/odd hostname.
  • One source, many accounts: several distinct user.name values sharing one access_device.ip across a short window.
  • Admin changes after a suspicious login: an action such as user_update shortly after an anomalous authentication, especially if the object is the same account.

The free browser analyzer runs these checks on a Duo JSON export locally, without uploading it.

Detections and guides for Duo Security

Frequently Asked Questions

Does an ALLOW in Duo mean the password was legitimate?
No. Duo records the second-factor decision for an application integration; the primary credential check usually happens in the SSO provider, VPN concentrator or application in front of Duo. An ALLOW only proves the factor was satisfied, which is exactly what an attacker achieves with a phished passcode, a stolen bypass code or a push the user approved by mistake.
Why do some records have no result, user or access_device?
Because authentication and administrator events sit in the same array. The third object in the benign sample has action, username, object and description instead — a parser that keys on result or user.name will drop it or throw. Branch on event_type and the presence of action before reading authentication-only fields.
How do I separate a user denying their own push from an attack?
Read the reason and the surrounding records for the same user. Isolated denials with ordinary reasons are routine. A cluster of denials within minutes, from one access_device.ip the user has never used, followed by an ALLOW, is the fatigue pattern — and a FRAUD result with reason user_marked_fraud means the user explicitly reported it, so treat the password as compromised.
Can I trust access_device.hostname and browser?
Only as leads. Both are reported by the client, so they can be absent, null or chosen by the attacker — the malicious sample contains the hostname attacker.ru and the browser python-requests. Corroborate with the source IP, the application involved and endpoint or EDR telemetry before concluding which machine was really used.

Analyze Duo Security logs

LogTriage auto-detects this format, enriches every IP, user agent and hash with threat intelligence, and writes an incident report mapped to MITRE ATT&CK.