A request that invalidates an OAuth session still runs once as the old user (global middleware next() without clearing request.user)
- Dominant language
- JavaScript
- Stars
- 1
- Forks
- 1
- Avg merge
- 2d 16h
- Merged PRs (30d)
- 12
Description
Surfaced during the #211 cross-model review. **Verified in code; not yet reproduced** — needs a PoC before a fix.
### Problem
Harper resolves `request.user` from `session.user` early (core auth middleware) — before the plugin's global session-validation middleware runs. That middleware (`src/index.ts` ~L419–437) detects an expired/revoked token or a removed provider, calls `clearOAuthSession(...)` to invalidate the STORED session, then unconditionally `return next(request)` — **without clearing `request.user` or rejecting the request.** So the request that triggered detection completes **once** with the old (now-invalidated) identity.
The stored session is invalidated, so subsequent requests are unauthenticated — but there's a one-request window where a user whose OAuth token was revoked upstream can still perform a protected operation. For a `super_user` that one operation is significant. (Resources wrapped with `withOAuthValidation` + `requireAuth: true` are denied by the wrapper; this gap is for the global path relying on Harper's `request.user`.)
### Scope / severity
One-request window after upstream revocation/expiry; pre-existing (the middleware has always `next()`-ed). Real but bounded auth gap.
### Direction (to design after reproduction)
On invalidation, short-circuit (return 401/deny) or clear `request.user` / request-local session state before continuing, rather than passing through. Decide whether the global middleware should enforce or remain passive with the wrapper as the sole gate. Reproduce first (login, revoke upstream token, one more request, assert it should be denied).
Priority suggestion: P2.
Contributor guide
Research direction
Start with the global session-validation middleware in src/index.ts around lines 419–437 and reproduce the reported flow: log in, revoke the upstream OAuth token, then make one more protected request. Confirm whether the request still uses request.user, then define and implement the chosen denial or request-state-clearing behavior; done means the triggering request is denied and subsequent requests remain unauthenticated.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- authentication, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100