huudis.session.revoked.v1
Fires when a session (or its associated refresh tokens) is revoked — whether by the user, by an admin, or by a cascading operation like password change.
Subscribe if you want to immediately invalidate any caches keyed on the session.
Not yet emitted in v1. Audit-log entries
auth.logout,session_revoked,session.revoked_all, andoidc_consent_revokedcarry equivalent data.
When it fires
- Explicit sign-out at
/v1/auth/logout. - User-initiated revoke at
/v1/account/sessions/:id/revokeor/v1/account/sessions/revoke-all. - Admin-initiated revoke at
/v1/ops/end-users/:id/revoke(cascades through every consent + refresh token for that user in the workspace's clients). - Password change at
/v1/account/password-change— all sessions except the current one are revoked, generating one event per revoked session. - User disable (
huudis.user.disabled.v1fires alongside, plus asession.revokedper active session). - Consent revoke at
/v1/account/connected-apps/:id.
Payload
{
"id": "evt_01KPG…",
"type": "huudis.session.revoked.v1",
"createdAt": "2026-05-12T23:14:00.000Z",
"data": {
"sessionId": "sess_01KPG…",
"userId": "usr_01KPG…",
"userEmail": "adi@forjio.com",
"clientId": "oc_plugipay_portal",
"reason": "user_initiated",
"revokedAt": "2026-05-12T23:14:00.000Z",
"revokedBy": "usr_01KPG…"
}
}
reason values:
| Value | Trigger |
|---|---|
user_initiated |
User clicked sign-out or revoked from connected-apps. |
admin_revoke |
Admin called the ops endpoint. |
password_change |
Cascade from password change. |
mfa_change |
Cascade from MFA enrolment or removal. |
user_disabled |
Cascade from user disable. |
expired |
Natural expiry. Reserved — not currently emitted; expired sessions are silently dropped. |
revokedBy is null for natural expiry or password_change; otherwise the usr_… that initiated.
Handler examples
// Node — invalidate per-session caches
if (event.type === 'huudis.session.revoked.v1') {
const s = event.data;
await cache.invalidate(`session:${s.sessionId}`);
if (s.reason === 'user_disabled') {
await db.users.update(s.userId, { disabled: true });
}
}
# Python
if event["type"] == "huudis.session.revoked.v1":
s = event["data"]
cache.invalidate(f"session:{s['sessionId']}")
What to do
- Invalidate any access-token-keyed caches you maintain.
- For
user_disabledreason, treat as a stronger signal and revoke everything you have for the user (same ashuudis.user.disabled.v1). - For
admin_revoke, log it — this is a manual intervention that may be incident-related.
Avoid:
- Notifying the user. They already initiated it (
user_initiated) or were the target of an admin action (admin_revoke); a webhook-driven email would be noisy or alarming.
Common pitfalls
- Bulk revoke storms. Calling
revoke-allfires one event per revoked session — can be dozens. Your endpoint should handle bursts; retries pile up if you 5xx. - Order vs. session.created. Deliveries aren't strictly ordered — revoke can arrive before the corresponding created event in pathological retry scenarios. Idempotent-upsert by
sessionIdand compare timestamps if you need a happens-before.
Related events
huudis.session.created.v1— counterpart.huudis.user.disabled.v1— the cascade-source forreason: "user_disabled".
Next
- Account → Sessions — self-service.
- End users → Revoke — admin path.