Skip to content

feat: revoke tokens server-side on auth logout (best-effort RFC 7009) - #17

Merged
nycomp merged 1 commit into
mainfrom
feat/logout-token-revocation
Oct 1, 2026
Merged

nycomp merged 1 commit into
mainfrom
feat/logout-token-revocation

Conversation

@nycomp

@nycomp nycomp commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

campus auth logout now attempts server-side token revocation (RFC 7009) before clearing local credentials. Previously it only deleted the local keyring/file entries, leaving the refresh token valid on the auth server until natural expiry — a copied or stolen token survived logout entirely.

Found during the 2026-10-01 auth posture review of campus-cli.

Design decisions

  • Revokes refresh token first, then access token (RFC 7009 token_type_hint on each), both bound to client_id=guest (public client — no secret).
  • Best-effort, never fatal: any failure (network error, non-200, endpoint not deployed) degrades to a local-only logout with a single dim note: "server-side token revocation was unavailable; local credentials were cleared." Offline logout works.
  • The logged-out no-op path makes no network calls (preserves PR fix: make auth logout a friendly no-op when not logged in #10's friendly no-op and keeps it offline).
  • Timeout is 10s per call so logout stays bounded.

Server-side prerequisite

The auth server has no revocation endpoint today — POST /auth/v1/oauth/revoke returns 404 on dev (probed 2026-10-01). Until it ships, every logout shows the dim note and clears locally; once it lands, revocation activates with no CLI change. Tracked as nyjc-computing/campus#677 (implementation notes for the server side are in that issue).

Related upstream issues filed from this review:

Doc refresh (included)

Test plan

  • 3 new unit tests for revoke_token: RFC 7009 payload + 200→True, non-200→False, network error→False (84 total, all passing).
  • 2 new/updated integration tests: logout calls revocation with the stored tokens (refresh first, then access) and still clears local state when revocation fails; the not-authenticated no-op asserts no revocation call.
  • ruff check clean; pre-commit smoke and pre-push lint hooks pass.

Verification note

Not exercised against the live dev server (a real logout would revoke the developer's stored token); behavior is pinned by the mocked tests above, and the live 404/no-endpoint path is exactly what the degradation tests simulate.

campus auth logout previously only deleted local credentials, leaving the
refresh token valid server-side until natural expiry. Logout now attempts
RFC 7009 revocation of the refresh and access tokens before clearing local
state.

Revocation is best-effort by design: logout still succeeds when the auth
server is unreachable or deployed without /oauth/revoke (currently the
case on dev — tracked in nyjc-computing/campus#677), with a dim note that
only local credentials were cleared. The logged-out no-op path makes no
network calls.

Also refreshed docs: PRD logout/authentication-flow sections, corrected
the stale 'CAMPUS_ENV' login docstring (actual variable is CAMPUS_AUTH_URL)
and the stale 'Configurable API endpoint' PRD line (flag removed in PR #11).

Discovered en route and filed upstream: refresh_token grant unimplemented
on the deployed dev server (nyjc-computing/campus#678), which breaks CLI
auto-refresh live.
@nycomp
nycomp merged commit 6f63567 into main Oct 1, 2026
1 check passed
@nycomp
nycomp deleted the feat/logout-token-revocation branch October 1, 2026 03:27
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.

2 participants