Okta Event Hooks to an Internal Security Service Using Skooh
Forward Okta security events to your SIEM with proper authentication and audit trails.
Overview
Okta Event Hooks notify your systems about security events: logins, MFA challenges, user lifecycle changes, and suspicious activity. These events belong in your SIEM—but your SIEM is internal.
Skooh bridges Okta to your private security service.
Setting Up
1. Create Skooh Endpoint
- Create endpoint in Skooh
- Copy URL: `https://api.skooh.io/hook/okta-security\`
2. Run the Skooh Proxy
Using the Desktop App:
- Download the Skooh Desktop App
- Enter your API key and hook token
- Set forwarding URL (e.g., `http://localhost:8080/webhooks/okta\`)
- Click Connect
Using Docker:
docker run -d \\
--name skooh-okta \\
-e SKOOH_TOKEN=okta-security \\
-e SKOOH_API_KEY=your_api_key \\
-e FORWARD_URL=http://siem-collector:8080/webhooks/okta \\
--restart unless-stopped \\
skooh/proxy
3. Configure Okta Event Hook
Note: See Okta's Event Hooks documentation for current setup instructions.
In Okta Admin Console:
- Go to Workflow → Event Hooks
- Click Create Event Hook
- Enter your Skooh URL
- Select events to subscribe to
- Complete verification (see below)
Okta Verification Challenge
Okta verifies your endpoint with a one-time challenge:
app.get('/webhooks/okta', (req, res) => {
// Okta sends verification as GET request
const challenge = req.headers['x-okta-verification-challenge'];
if (challenge) {
return res.json({ verification: challenge });
}
res.status(400).send('Missing challenge');
});
Handling Okta Events
app.post('/webhooks/okta', express.json(), async (req, res) => {
// Verify authorization header
const authHeader = req.headers['authorization'];
if (authHeader !== \`Bearer \${process.env.OKTA_HOOK_SECRET}\`) {
return res.status(401).send('Unauthorized');
}
const { data } = req.body;
const { events } = data;
for (const event of events) {
await processOktaEvent(event);
}
res.status(200).send('OK');
});
async function processOktaEvent(event) {
const { eventType, actor, target, outcome, published } = event;
// Log to SIEM
await siemClient.log({
source: 'okta',
type: eventType,
timestamp: published,
actor: {
id: actor.id,
email: actor.alternateId,
displayName: actor.displayName
},
target: target.map(t => ({
id: t.id,
type: t.type,
displayName: t.displayName
})),
outcome: outcome.result,
reason: outcome.reason
});
// Alert on suspicious events
if (isSuspicious(event)) {
await alertSecurityTeam(event);
}
}
Key Security Events to Monitor
const HIGH_PRIORITY_EVENTS = [
'user.session.start', // Login
'user.authentication.sso', // SSO authentication
'user.mfa.factor.activate', // New MFA factor
'user.mfa.factor.deactivate', // MFA removed
'user.account.lock', // Account locked
'user.account.unlock', // Account unlocked
'user.lifecycle.suspend', // User suspended
'policy.evaluate_sign_on', // Sign-on policy evaluation
'security.threat.detected', // Threat detected
];
function isSuspicious(event) {
// Multiple failed logins
if (event.eventType === 'user.session.start' &&
event.outcome.result === 'FAILURE') {
return true;
}
// MFA bypass attempts
if (event.eventType.includes('mfa') &&
event.outcome.result === 'FAILURE') {
return true;
}
// Unusual location
if (event.client?.geographicalContext?.country !== expectedCountry) {
return true;
}
return false;
}
Event Filtering in Okta
Don't forward everything—Okta generates many events. Filter in Okta:
- In Event Hook settings, click Subscribe to events
- Choose specific event types:
- `user.session.start`
- `user.authentication.auth_via_mfa`
- `user.lifecycle.*`
- `security.threat.detected`
This reduces noise and ensures you focus on security-relevant events.
Audit Trail via Skooh Inspector
Skooh stores every webhook for 30 days. Use this for:
- Incident investigation: Find all events for a user/timeframe
- Compliance: Prove you received and processed security events
- Debugging: Replay events to test your handler
Replaying for Investigation
During a security incident:
- Filter webhooks by time window
- Find events related to the compromised account
- Replay to your analysis tools
- Build a timeline without touching production Okta
Written by Skooh Team