← All essays · 2026-08-11

"Deactivate in Okta" is not "access revoked"

A heavy vault door closed and locked, while dozens of glowing keys float out through the wall around it, drifting into the dark

I spend a lot of my time building offboarding automation. When I started, the moment a user object flipped to deactivated felt like the finish line. Deactivated meant gone.

It doesn’t. There is a gap between “deactivated” and “gone”, and that gap is where the risk of offboarding lives.

What the button actually does

Deactivating a user in Okta stops future authentications. Tomorrow morning, when the leaver types their password, nothing happens.

It does not close the browser tab they left open. It does not revoke OAuth refresh tokens or personal access tokens. It says nothing about local accounts in apps Okta never provisioned.

So imagine a leaver’s last day. The Okta account dies at 5 p.m. Their session in the on-call tool is alive at 6. The refresh token in their mail client keeps working until the issuing app says otherwise. Nothing dramatic has to happen. This is the default.

Where access hides

Even with SCIM connected, you are trusting a protocol with real ambiguity. SCIM gives an app two ways to hear “this person is gone”: a DELETE on the user, or a PATCH setting active to false. Some apps soft-delete, some hard-delete and destroy the audit trail, some ignore DELETE and only honor the PATCH.

Okta abstracts this per connector, so two apps behind the same termination can land in opposite states, and the admin console shows a green checkmark for both. The checkmark says the call was sent. It does not say the account is off.

Edge case? Identity-lifecycle surveys in 2026 put the share of former employees who still hold access to a previous employer’s systems at around 83 percent.

What “revoked” actually takes

Revocation is a pipeline with three jobs: stop new logins, kill live access, verify downstream. Deactivation only does the first.

Killing live access is one more API call:

POST   /api/v1/users/{userId}/lifecycle/deactivate
DELETE /api/v1/users/{userId}/sessions?oauthTokens=true

The second call clears sessions and revokes OAuth grants, so the open tab dies now.

Verification is where most pipelines go quiet. Okta’s System Log records what each connector actually sent: the application.provision.user.deactivate event carries the real HTTP call. Test each connector with a canary user and read it. The UI status is a summary written for optimists.

Then put a clock on it: a deactivation not followed by matching downstream deactivations within a set window should page someone, not wait for the next access review.

The button, revisited

The deactivate button does what its name says: it deactivates the user, in Okta. Every word after “in Okta” is your job.

This week, in a preview org: pick one SCIM-connected app, create a canary user, deactivate it. Check which verb the connector sent and whether the session survived. One test user, one screenshot, and you know whether your offboarding ends at a checkmark or at revoked.

fabioarao@porto — type `help`
~ $