Skip to main content

Okta

Overview​

Okta is a pull-based source that collects two kinds of Okta data into a Praxis pipeline:

DataOkta APIGoogle SecOps log typeDefault
System Log events — sign-ins, MFA challenges, admin changes, app assignments, policy evaluationsGET /api/v1/logsOKTAOn
User context — every user's current status, profile, manager, department and last loginGET /api/v1/usersOKTA_USER_CONTEXTOff

The original Okta JSON is preserved in the log body, so downstream parsers (for example the Google SecOps OKTA and OKTA_USER_CONTEXT parsers) receive the complete record. Every record carries the resource attribute okta.source (system_log or users) so you can route each kind to its own log type.

Supported types: Logs

Supported platforms: Linux, Windows, macOS

Minimum collector version: 0.3.16

Authentication​

Credential typeWhen to use
Bearer Token (bearertokenauth) with Auth Scheme = SSWSThe only supported option. Okta API tokens are sent as Authorization: SSWS <token>.

Create a bearertokenauth credential with two fields:

FieldValue
tokenAn Okta API token created under Security → API → Tokens in the Admin Console.
schemeSSWS

Important: the scheme field must be set to SSWS. Left blank it defaults to Bearer, and Okta rejects every request with 401 Unauthorized. Praxis will not deploy this source with any credential type other than bearertokenauth.

Note: an Okta API token inherits the permissions of the admin who created it, and expires after 30 days of non-use. Create it under a dedicated read-only service account with the Read-Only Administrator role — that covers both the System Log and the Users API.

OAuth 2.0 (okta.logs.read scope) is not yet supported. When it lands it will be additive; existing configurations stay valid.

Basic configuration​

ParameterTypeRequiredDefaultDescription
org_urlstring (URI)YesnoneOkta org base URL, e.g. https://acme.okta.com. Must be https, host-only — no path. The receiver appends /api/v1/logs and /api/v1/users.
system_log.enabledboolNotrueCollect System Log events. Turn off to run a source that collects only user context.
users.enabledboolNofalseCollect user context. See User context.
poll_intervalinteger (seconds)No30How often the System Log cursor is followed. Minimum 5, enforced to protect the org rate limit.
lookbackinteger (seconds)No3600Cold start only. How far back the first poll reaches when no cursor is persisted. Cap this to your org's log retention.
persist_offsetsboolNotrueCheckpoint the resume cursor so restarts neither duplicate nor skip events. See Resumption.
limitintegerNo1000Events fetched per request. Okta's maximum is 1000; values outside 1–1000 are rejected.
filterstringNononeServer-side SCIM filter expression, e.g. eventType eq "user.session.start". Filtering at Okta is far cheaper than dropping records downstream.
qstringNononeFree-text narrowing applied server-side.

In the pipeline editor, limit, filter and q appear inside the Advanced group, but they are top-level config keys — not nested under advanced.

advanced​

ParameterTypeDefaultDescription
timeoutinteger (seconds)30HTTP timeout for requests to Okta.
tls.insecure_skip_verifyboolfalseDisable TLS server certificate verification. Not recommended in production.
tls.ca_filestringnoneCustom CA bundle for verifying the Okta endpoint.

User context​

Turn on Collect User Context (users.enabled) to send every Okta user to the pipeline.

ParameterTypeDefaultDescription
users.modescheduled | manualscheduledscheduled: fetch all users every users.interval. manual: fetch all users only with Fetch Users Now.
users.intervalinteger (seconds)86400Time between snapshots in scheduled mode. Minimum 900 (15 minutes).
users.include_deprovisionedbooltrueInclude deactivated (DEPROVISIONED) users, which Google SecOps marks as DELETED.
users.sync_requestinteger0Fetch Users Now — the on-demand trigger, shown and used in manual mode only. See below.

Fetching users on demand​

Fetch Users Now appears only when User Fetch Mode is manual, and in that mode it is the only way users are fetched.

  1. Set User Fetch Mode to manual.
  2. In Fetch Users Now, enter a number higher than the current one (for example 1 → 2).

Resumption​

Okta's System Log API returns a Link: <url>; rel="next" header carrying an opaque, self-advancing cursor that excludes records already returned. The receiver follows that cursor and persists it only after a page has been delivered downstream — so a crash mid-pagination replays from the last durably-flushed cursor rather than skipping events.

With Persist Offsets on (the default), Praxis automatically provisions a storage extension for this node under the collector's metadata directory (<collector home>/metadata/okta_offsets/<node name>) and wires it for you. Nothing to configure.

Turn it off only for ephemeral collectors or read-only filesystems. Without persistence, every restart cold-starts from now - lookback and re-emits whatever falls in that window.

Output mapping​

Each System Log event becomes one log record.

Okta fieldOTel destination
(whole event JSON)LogRecord.Body (string)
publishedLogRecord.Timestamp (falls back to receive time if unparseable)
severityLogRecord.SeverityNumber / SeverityText — DEBUG/INFO/WARN/ERROR; anything unrecognised maps to INFO rather than being dropped
uuidLogRecord.Attributes["okta.uuid"]
eventTypeLogRecord.Attributes["okta.event_type"]
severityLogRecord.Attributes["okta.severity"]
displayMessageLogRecord.Attributes["okta.display_message"]
actor.id / actor.type / actor.alternateIdokta.actor.id / okta.actor.type / okta.actor.alternate_id
client.ipAddressLogRecord.Attributes["okta.client.ip"]
outcome.result / outcome.reasonokta.outcome.result / okta.outcome.reason
(constant)Resource.Attributes["vendor"] = "okta"
(from org_url host)Resource.Attributes["okta.org"]
(constant)Resource.Attributes["okta.source"] = "system_log"

Each user becomes one log record.

Okta fieldOTel destination
(whole user JSON)LogRecord.Body (string)
(snapshot start time)LogRecord.Timestamp — the record describes the user as of that snapshot
idLogRecord.Attributes["okta.user.id"]
statusLogRecord.Attributes["okta.user.status"]
profile.loginLogRecord.Attributes["okta.user.login"]
(constant)Resource.Attributes["vendor"] = "okta", Resource.Attributes["okta.source"] = "users"

The promoted attributes exist for routing and filtering — use them in routing conditions and processor matchers without paying to parse the body. The body itself is untouched, so a downstream parser still sees the complete record.

Example configuration​

{
"org_url": "https://acme.okta.com", // required
"poll_interval": 30, // default: 30, minimum 5
"lookback": 3600, // default: 3600 (cold start only)
"persist_offsets": true, // default: true
"limit": 1000, // default: 1000 (Okta max)
"filter": "eventType eq \"user.session.start\"",
"users": {
"enabled": true, // default: false
"mode": "scheduled", // default: scheduled
"interval": 86400, // default: 86400, minimum 900
"include_deprovisioned": true, // default: true
"sync_request": 1 // raise and deploy to fetch all users now
},
"advanced": {
"timeout": 30, // default: 30
"tls": { "insecure_skip_verify": false }
}
}

Operational notes​

  • Rate limits. The System Log API is rate-limited per org (and shared with everything else using the Okta API). A poll_interval of 30s at limit: 1000 comfortably sustains a busy org; going below the 5s floor is rejected outright.
  • Filter at the source. filter and q are evaluated by Okta before the response is built. Narrowing there costs nothing; dropping the same records in a processor costs a full fetch, parse and pipeline traversal.
  • Lookback vs retention. On a cold start the receiver asks for now - lookback. Setting lookback beyond your org's System Log retention just produces an empty first page.
  • Polling, not streaming. For very high volumes on AWS, Okta Log Streaming → S3 ingested via the AWS S3 source is an alternative delivery path.
  • Event Hooks are not used. They deliver only a curated subset of event types; the System Log API is the complete source of record.

Metrics​

Metric NameDescription
prx_src_records_received_total{signal="logs"}Log records emitted, one per System Log event or user.
prx_src_bytes_received_totalAPI response bytes read from Okta.
prx_src_pipeline_latency_secondsArrival → downstream handoff.
prx_src_errors_total{reason}Source errors by reason — io for request failures.
prx_src_parse_errors_total{parser="json"}Malformed event or user page returned by Okta.
prx_src_records_dropped_total{reason="backpressure"}Records dropped because the downstream pipeline refused them.