Skip to content

fix: answer 200 for a token the revocation endpoint cannot revoke - #29384

Draft
BobbyHo wants to merge 1 commit into
mainfrom
coder-plat-507-revoke-invalid-token
Draft

BobbyHo wants to merge 1 commit into
mainfrom
coder-plat-507-revoke-invalid-token

Conversation

@BobbyHo

@BobbyHo BobbyHo commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

POST /oauth2/revoke returned 500 when the token's secret did not match a stored token, and when the token was a valid API key that OAuth2 did not issue. An unknown token returned 200. The difference told the caller which tokens exist.

  • A wrong token secret and a non-OAuth2 API key now return 200, as RFC 7009 asks
  • A malformed token still returns 400, and a database failure still returns 500
  • Nothing is revoked in any of these cases
  • Tests cover a wrong refresh secret, a wrong access token secret, and a session token from another login

Found in review of #29208 and deferred from it.

@linear-code

linear-code Bot commented Sep 16, 2026

Copy link
Copy Markdown

PLAT-507

@BobbyHo

BobbyHo commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review

coder-agents-review Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Chat: Review in progress (17/17 reviewers complete) | View chat
Requested: 2026-09-16 00:34 UTC by @BobbyHo

deep-review v0.9.0 | Round 1 | 800629c..fc314ae

Last posted: Round 1, 7 findings (3 P3, 2 Nit, 2 Note), COMMENT. Review

Finding inventory

Finding inventory, PR #29384

Findings

# Sev Status Location Summary Round Reviewer Posted
CRF-1 P3 Open oauth2_test.go:1092 CrossApp doc comment orphaned above the inserted InvalidToken test R1 Leorio P2, Zoro P3, Netero P3, Bisky/Pariston/Kurapika/Knov/Kite/Meruem Nit Yes
CRF-2 P3 Open revoke.go:31 ErrNoSuchToken names the opposite of its condition (returned for found-but-invalid, not absent) R1 Gon P3, Zoro Note, Mafuuu Note Yes
CRF-3 P3 Open revoke.go:104 Debug log "no token matches the one presented" is false for the non-OAuth2 login-type path and collapses three causes R1 Leorio P3, Chopper Note, Meruem Note Yes
CRF-4 Nit Open oauth2_test.go:1107 replaceLast keeps the last sep and overwrites after it; name says "replace the last sep" R1 Gon Yes
CRF-5 Nit Open oauth2_test.go:1100 "OAauth2" typo copied into the new nolint justification R1 Netero, Knov Yes
CRF-6 Nit Open PR title Commit subject is 73 chars, one over the 72 limit R1 Leorio No (body)
CRF-7 Note Open revoke.go:101 Refresh path timing distinguishes existing prefix from absent; near-zero practical value R1 Hisoka, Mafuuu, Knov, Razor Yes
CRF-8 Note Open revoke.go:101 Handler default is fail-open-to-500; new validation branches must remember the sentinel or reopen the oracle R1 Pariston, Meruem Yes

Round log

Round 1

Netero-only pre-pass: P3 doc-comment displacement + Nit typo. Panel (16): bisky, hisoka, mafu-san, mafuuu, pariston, kurapika, knov, razor, chopper, kite, ging-go, komugi, gon, leorio, meruem, zoro. Production change verified sound: the three ErrNoSuchToken sites close the status-code existence oracle, all three covered distinctly by TestOAuth2ProviderRevokeInvalidToken (per-block coverage confirmed by multiple reviewers). No P0-P2 confirmed. 3 P3, 2 Nit posted inline, 1 Nit in body, 2 Notes. Reviewed against 800629c..fc314ae.

About deep-review

CRF = Coder Review Finding (P0-P4, Nit, Note)

Reviewer Focus
Bisky tests
Chopper ops/errors
Churn-guard change verification
Ging language modernization
Gon naming
Hisoka edge cases
Killua perf
Kite change integrity
Knov contracts
Knuckle SQL
Komugi flake/determinism
Kurapika security
Law decomposition
Leorio docs
Luffy product
Mafu-san process
Mafuuu contracts
Melody dispatch/pairing
Meruem structural
Nami frontend
Netero mechanical checks
Pariston premise testing
Pen-botter product gaps
Razor verification
Robin duplication
Ryosuke Go arch
Takumi concurrency
Zoro shape

🤖 Managed by Coder Agents.

@coder-agents-review coder-agents-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The production change is small and does what it claims: the three in-tx validation failures (wrong refresh secret, wrong API-key secret, valid non-OAuth2 API key) that previously fell through to a 500 now return ErrNoSuchToken -> 200, matching the unknown-token and cross-app paths. That closes the status-code existence oracle described in the PR body, per RFC 7009 §2.2, and revokes nothing on any refused path. Multiple reviewers ran TestOAuth2ProviderRevokeInvalidToken with per-block coverage and confirmed all three new returns (revoke.go:151, :191, :196) and the handler's 200 branch each execute, with the staysValid case proving a real non-OAuth2 session survives the refused revoke. The PR description is accurate against the code and was singled out for praise.

No P0-P2 confirmed. Findings: 3 P3 (a displaced doc comment, the sentinel's misleading name, and an inaccurate debug log), 2 Nits, and 2 Notes.

The doc-comment displacement (CRF-1) was independently flagged by nine reviewers; Leorio rated it P2, but the consequence is documentation-only in a test file, so I settled it at P3. The naming and log findings (CRF-2, CRF-3) are the same underlying fact from two angles: ErrNoSuchToken is returned only when a token record IS found but fails validation (the genuinely-absent sql.ErrNoRows paths return nil), and for the non-OAuth2 case a token exists and its secret matched, so both the identifier and the log line "no token matches the one presented" misdescribe that path.

Process: the commit subject is 73 characters, one over the 72-char limit (Leorio). Trimming a word keeps the scenario intact.

Hisoka, after trying to break the endpoint: "I came to fight the revocation endpoint and it held its ground."

🤖 This review was automatically generated with Coder Agents.

Comment thread coderd/oauth2_test.go
Comment thread coderd/oauth2provider/revoke.go Outdated
Comment thread coderd/oauth2provider/revoke.go Outdated
Comment thread coderd/oauth2_test.go Outdated
Comment thread coderd/oauth2_test.go Outdated
Comment thread coderd/oauth2provider/revoke.go Outdated
Comment thread coderd/oauth2provider/revoke.go Outdated
@BobbyHo BobbyHo changed the title fix(coderd): answer 200 for a token the revocation endpoint cannot revoke fix: answer 200 for a token the revocation endpoint cannot revoke Sep 16, 2026
@BobbyHo
BobbyHo force-pushed the coder-plat-507-revoke-invalid-token branch 2 times, most recently from 5923f7e to ef17afe Compare September 16, 2026 16:52
…voke

- A wrong token secret, or a valid API key that is not an OAuth2 token,
  returned 500. That told the caller the token existed.
- These cases now return 200, as RFC 7009 asks. A malformed token still
  returns 400, and a database failure still returns 500.
- Add tests for a wrong refresh secret, a wrong access token secret, and a
  session token from another login.
@BobbyHo
BobbyHo force-pushed the coder-plat-507-revoke-invalid-token branch from ef17afe to f7116aa Compare September 16, 2026 17:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant