onscryn

Access should end on the next request, not the next expiry

When someone is removed, how long can they still get in? For many systems the honest answer is: until their token runs out.

By the Onscryn team · November 1, 2026 · 8 min read

Here is a test worth running on any system you rely on. Remove a user, then try to use their old session. How long does it keep working? The answer is more varied, and more often uncomfortable, than most teams expect.

Why tokens outlive the person

Modern sign-in is built on tokens: small signed pieces of data that say who you are and until when. Their great virtue is that a server can check one without asking anyone. No database lookup, no round trip. That is what makes them fast and easy to scale.

Their great weakness is the same property. Because the server does not ask anyone, it cannot know you were removed five minutes ago. The token is signed, it has not expired, so it is accepted. The only thing that ends it is the clock.

WAITING FOR THE TOKEN TO EXPIREaccess removedtoken expiresstill works for all of thisCHECKING ON EVERY REQUESTaccess removednext request: refusednothing left to expire
Two ways to end access. The first leaves a window. The second leaves nothing to wait for.

The usual workarounds

Teams respond in a few predictable ways. They shorten token lifetimes, which shrinks the window and multiplies the sign-ins. They keep a revocation list that every server must consult, which reintroduces the lookup they were avoiding. Or they accept the window and write 'up to 15 minutes' in a policy document.

None of these is crazy. But a window of minutes is a long time for someone who has just left under difficult circumstances, and it is an awkward thing to explain to a customer or auditor who asks 'when exactly does their access end?'

Check a version on every request

A simpler idea is to give each user a version number that changes when anything about their access changes: they are removed, demoted, signed out everywhere. The token carries the version it was issued under. On every request, the server compares it with the current one. A mismatch means the token is stale, and the request is refused.

It sounds like it should be expensive. In practice it is a single small read, often from a fast cache, and most systems already touch some store on each request. The marginal cost is low, and what you buy is an answer you can state in one sentence: their next request fails.

Do the long-lived connections too

Requests are only half the story. A streaming session is a long-lived connection, and a check at the start does not help if it then runs for hours. The fix is to tie the connection to a ticket that is valid for that exact session, and to have the server close any connection that does not present one. Removal then has two edges: the next request is refused, and a connection without a valid ticket is not allowed to continue.

The Sessions page of the Onscryn dashboard showing live and ended sessions
Sessions in one view, so ending someone's access also means seeing what they had open. Demo organization.

What to ask your own systems

  • When I remove a person, what exactly stops them, and when?
  • Does a role change take effect on the next action or at the next sign-in?
  • What happens to a connection that is already open?
  • Is the answer the same for people signing in through an identity provider?

If the answer to the first question involves the word 'eventually', you have found something worth fixing.

Curious how this looks
on your own app?