🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

feat: handle revoked OAuth grants for MCP servers gracefully - #27264

Merged
ibetitsmike merged 5 commits into
mainfrom
mike/mcp-revoked-oauth-grants
Jul 16, 2026
Merged

feat: handle revoked OAuth grants for MCP servers gracefully#27264
ibetitsmike merged 5 commits into
mainfrom
mike/mcp-revoked-oauth-grants

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Closes CODAGT-792.

When a user revokes an upstream OAuth grant for an MCP server used by Coder Agents, Coder kept treating the cached token as valid: invalid_grant refresh failures were logged and swallowed, the dead bearer token kept being attached, the list endpoints re-attempted the refresh on every call, and the UI kept showing the server as authenticated.

Changes

Backend, mirroring the external_auth_links prior art:

  • New migration adds mcp_server_user_tokens.oauth_refresh_failure_reason. UpsertMCPServerUserToken clears it, so completing the OAuth flow again recovers the row.
  • New MarkMCPServerUserTokenRefreshFailure query records the failure and clears all token material, guarded by an updated_at optimistic lock so a stale failure never clobbers a concurrently refreshed token (on a lock miss the winner's row is used).
  • mcpclient.IsPermanentRefreshError classifies *oauth2.RetrieveError codes: only invalid_grant and bad_refresh_token are permanent. Client/config errors (invalid_client, unauthorized_client, ...) stay transient for the user row since reconnecting cannot fix them.
  • chatd token refresh and the MCP list/get endpoints persist permanent failures, return cleared tokens for the in-flight request, and skip provider calls for already-failed rows.
  • buildAuthHeaders no longer attaches an Authorization header for failed tokens, so chat degrades by omitting that server's tools instead of sending a dead bearer.

API and UI:

  • No new API surface. A permanently failed token simply reports auth_connected: false, so the existing "Auth" button and "Not authenticated" tooltip appear and the user re-runs the same OAuth flow to recover. An earlier revision added an auth_status enum (connected / not_connected / reconnect_required) with a dedicated "Reconnect" button; it was collapsed to keep the API minimal since both states lead to the identical re-auth action.

Out of scope (follow-up): typed 401-on-connect detection and forced refresh. mcp-go exposes no stable typed 401 signal in the static-header path, so a revocation while the access token still looks valid locally stays undetected until expiry triggers a refresh.

Testing

  • Unit and integration tests: classifier, chatd refresh paths (permanent/transient/race/persist-failure), API endpoints (revoked, transient, no-retry caching, re-auth recovery, stale-lock), dbauthz, dbcrypt, migrations.
  • Dogfood UAT against a dev instance with a mock IdP returning invalid_grant: revoked grant detected on refresh and persisted once (no repeated IdP calls), chat with the revoked server selected completes with the server's tools omitted, and re-auth restores the connected state.

This PR was authored by Mux, working on Mike's behalf.

@linear-code

linear-code Bot commented Jul 15, 2026

Copy link
Copy Markdown

CODAGT-792

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3cfe876d0e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread codersdk/mcp.go Outdated
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 377c826493

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 13903f1aeb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: 4b987cf37d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
ibetitsmike marked this pull request as ready for review July 16, 2026 11:26
@ibetitsmike
ibetitsmike force-pushed the mike/mcp-revoked-oauth-grants branch from 4b987cf to 03ac55c Compare July 16, 2026 11:31
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 03ac55c6bd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
ibetitsmike enabled auto-merge (squash) July 16, 2026 11:40
@ibetitsmike
ibetitsmike merged commit e489092 into main Jul 16, 2026
28 of 29 checks passed
@ibetitsmike
ibetitsmike deleted the mike/mcp-revoked-oauth-grants branch July 16, 2026 11:43
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 16, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants