Identity ✓ fields verified against sample logs

Okta System Log Format: Field Reference With Examples

Published

One record per event in an Okta org — a login attempt, a factor verification, a logout, an account lockout — showing who or what acted, the client and IP behind it, and whether it succeeded.

Sample record

  {"eventType":"user.session.end","published":"2024-03-15T17:30:00.000Z","displayMessage":"User logout from Okta","outcome":{"result":"SUCCESS"},"actor":{"alternateId":"[email protected]","displayName":"Alice Smith","type":"User"},"client":{"ipAddress":"203.0.113.42","userAgent":{"rawUserAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/123.0.0.0 Safari/537.36","os":"Mac OS X","browser":"Chrome"},"geographicalContext":{"country":"US","city":"Seattle"}},"securityContext":{"asNumber":7224,"asOrg":"Amazon.com","isp":"Amazon Web Services","domain":"aws.com"}},
  {"eventType":"user.session.start","published":"2024-03-15T10:15:00.000Z","displayMessage":"User login to Okta","outcome":{"result":"FAILURE","reason":"INVALID_CREDENTIALS"},"actor":{"alternateId":"[email protected]","displayName":"Charlie Brown","type":"User"},"client":{"ipAddress":"203.0.113.99","userAgent":{"rawUserAgent":"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15","os":"iOS","browser":"Mobile Safari"},"geographicalContext":{"country":"US","city":"Chicago"}},"securityContext":{"asNumber":7922,"asOrg":"Comcast","isp":"Comcast Cable","domain":"comcast.net"}},
  {"eventType":"user.session.start","published":"2024-03-15T10:15:30.000Z","displayMessage":"User login to Okta","outcome":{"result":"SUCCESS"},"actor":{"alternateId":"[email protected]","displayName":"Charlie Brown","type":"User"},"client":{"ipAddress":"203.0.113.99","userAgent":{"rawUserAgent":"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15","os":"iOS","browser":"Mobile Safari"},"geographicalContext":{"country":"US","city":"Chicago"}},"securityContext":{"asNumber":7922,"asOrg":"Comcast","isp":"Comcast Cable","domain":"comcast.net"}}

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

Field reference

Field Type Meaning Why it matters for security
eventTypee.g. user.session.start string Structured name of the event. The samples contain user.session.start, user.authentication.auth_via_mfa, user.session.end and user.account.lock. The first filter in any hunt — authentication and lockout event types carry the credential-attack signal.
publishede.g. 2024-03-15T09:01:00.000Z datetime (UTC) When Okta recorded the event, ISO 8601 with milliseconds. Sort on this rather than on position in the file; exported records are not always in time order.
displayMessagee.g. User login to Okta string Human-readable description of what happened. Readable in a timeline, but match on eventType — message text is not a stable key.
outcome.resulte.g. SUCCESS string Whether the attempt succeeded. Both SUCCESS and FAILURE appear in the samples. A run of FAILURE events followed by one SUCCESS from the same IP is the credential-stuffing shape.
outcome.reasone.g. INVALID_CREDENTIALS string Why a failure failed. The samples show INVALID_CREDENTIALS and FACTOR_CHALLENGE_TIMEOUT; the field is absent on the successful events. INVALID_CREDENTIALS across many accounts from one source is spraying or stuffing; FACTOR_CHALLENGE_TIMEOUT after a successful password means the attacker has the credential but stopped at MFA.
actor.alternateIde.g. [email protected] string Identifier of whoever or whatever triggered the event, normally the user's login name. Counting distinct values per source IP is how stuffing is found — but on system-generated events this is not the victim.
actor.displayNamee.g. Alice Smith string Display name of the actor. Good for timelines, bad as a join key — it is not unique and users can share names.
actor.typee.g. User string Kind of principal that acted. The samples show User and SystemPrincipal. SystemPrincipal means Okta itself generated the event, such as the automatic account lockout in the malicious sample.
client.ipAddresse.g. 203.0.113.42 string Source IP address Okta saw for the request. The main pivot — grouping failures by IP separates one user mistyping a password from one host hitting many accounts.
client.userAgent.rawUserAgente.g. python-requests/2.28.0 string Raw User-Agent header sent by the client. HTTP libraries such as python-requests on interactive logins mean automation, not a person at a keyboard.
client.userAgent.ose.g. Mac OS X string Operating system Okta parsed out of the user agent; Unknown when it cannot parse one. os and browser both Unknown usually means a non-browser client such as a script.
client.userAgent.browsere.g. Chrome string Browser parsed out of the user agent; Unknown when it cannot be identified. A fleet-wide shift to an unparsed browser on one account is worth checking against the raw agent string.
client.geographicalContext.countrye.g. US string Country derived from the source IP address. Two countries for one account within minutes is impossible travel — remember the value is geolocation, not ground truth.
client.geographicalContext.citye.g. Seattle string City derived from the source IP address. City-level changes are noisy on mobile and VPN traffic; treat country and ASN as the stronger signals.
securityContext.asNumbere.g. 7224 integer Autonomous system number Okta associated with the source IP. One ASN behind failures against many accounts points at a single hosting provider or proxy pool rather than scattered users.
securityContext.ispe.g. Comcast Cable string ISP name associated with the source IP, alongside asOrg and domain. Hosting and anonymiser networks on a user login are a strong enrichment signal; residential proxies still look like consumer ISPs.

What it records

Each record in the Okta System Log is one event in an Okta org: a login attempt, a factor verification, a logout, an account lockout, an administrative change. The record says what happened (eventType, displayMessage), how it ended (outcome.result and, on failures, outcome.reason), who or what caused it (the actor object) and where it came from (client.ipAddress, the parsed client.userAgent, client.geographicalContext and the IP enrichment in securityContext).

One sign-in is usually more than one record. In the benign sample, Alice’s login produces a user.session.start at 09:01:00 and a user.authentication.auth_via_mfa at 09:01:05; her logout is a separate user.session.end eight hours later. Reconstruct sessions by correlating actor.alternateId, client.ipAddress and published, not by reading a single event.

Where to get it

  • Admin console → Reports → System Log, which supports search and filtering and a CSV download. Convenient for a quick look, limited for bulk work.
  • System Log API, GET /api/v1/logs, with since and until parameters and cursor-based pagination through the Link response headers. It returns a JSON array of event objects shaped like the samples on this page (with more fields).
  • Log streaming / SIEM collectors. Most SIEM integrations poll the API on a schedule; where your tenant supports Okta’s log streaming feature it can push events to a cloud destination instead.

Console retention is finite and depends on your org, so forward events to your SIEM or object storage if you need months of history for investigations that start late.

Parsing pitfalls

  • outcome.reason only exists on failures. The SUCCESS records in the samples have no reason key at all. Code that reads it unconditionally will throw or silently produce nulls.
  • Export order is not time order. In the benign sample the 17:30 user.session.end appears before the 10:15 events. Sort on published before building a timeline.
  • The actor is not always the subject. On user.account.lock the actor is [email protected] with actor.type of SystemPrincipal. Grouping lockouts by actor.alternateId attributes them to Okta rather than to the locked user.
  • Geolocation and ASN are derived. client.geographicalContext and securityContext come from IP enrichment, so VPNs, carrier NAT and cloud egress produce plausible but wrong locations — and enrichment labels can be stale or odd.
  • os and browser can be Unknown. They are parsed from rawUserAgent; keep the raw string, that is where python-requests/2.28.0 shows up.
  • Array versus NDJSON. These files are JSON arrays; API pages and streaming destinations may hand you one object per line. Handle both.

Detection ideas

  • Credential stuffing: one client.ipAddress with outcome.result FAILURE and outcome.reason INVALID_CREDENTIALS across many distinct actor.alternateId values in minutes — nine accounts in twenty seconds in the malicious sample. This is the Okta credential stuffing rule.
  • Scripted client: rawUserAgent of an HTTP library, with os and browser both Unknown, on user.session.start.
  • A hit inside the burst: a SUCCESS user.session.start from the same IP that just produced the failures — that account’s password is known.
  • Password valid, MFA held: a successful user.session.start followed by user.authentication.auth_via_mfa with FAILURE and reason FACTOR_CHALLENGE_TIMEOUT. Reset the password anyway; MFA was the only thing standing in the way.
  • Lockout clusters: several user.account.lock events sharing one client.ipAddress.
  • Impossible travel: successful sessions for one actor.alternateId from two distant client.geographicalContext.country values within an implausible interval.

The same reasoning applies to Microsoft estates with different field names — see the Entra ID sign-in log reference. To run these checks on an export without uploading it anywhere, use the browser log analyzer.

Detections and guides for Okta System Log

Frequently Asked Questions

Why does a user.account.lock event show [email protected] as the actor?
Because Okta, not the user, performed the lockout, so actor.type is SystemPrincipal and actor.alternateId is the system account. The locked user is not in the actor object of that event — in full API records the affected account appears in the target array, and in trimmed exports like the sample you have to identify the victim from the failed logins immediately before, correlating on client.ipAddress and published.
What is the difference between user.session.start and user.authentication.auth_via_mfa?
They are separate records for separate stages. In the benign sample Alice's login is a user.session.start with SUCCESS at 09:01:00 followed by user.authentication.auth_via_mfa with SUCCESS five seconds later. A successful session.start with a failed auth_via_mfa, as in the malicious sample, means the password was accepted and only the second factor stopped the attacker.
How do I tell a user fumbling their password from credential stuffing?
Group on client.ipAddress and count distinct actor.alternateId values. One account failing repeatedly from its usual IP, browser and city is a human; one IP producing INVALID_CREDENTIALS against nine different accounts in twenty seconds with a python-requests user agent, as in the malicious sample, is automated credential testing.
Do the samples show every field an Okta System Log record contains?
No. These files are trimmed to the fields that matter for authentication analysis. Records returned by the System Log API also carry identifiers and context such as uuid, severity, transaction and the target array, so write parsers that ignore unknown keys rather than assuming this exact shape.

Analyze a Okta System Log file in your browser

The free analyzer detects this format, parses every field above and flags attack patterns — the file never leaves your machine. For threat-intel enrichment and an AI-written incident report, run it through LogTriage.