Skip to content

Remote MCP (OAuth): active session keeps resending an expired access token instead of refreshing or prompting sign-in #5233

Open

Description

@liu1700

Describe the bug

A Copilot CLI session connected to a remote OAuth-protected MCP server keeps sending the same expired access token after its first HTTP 401. The client makes no request to the token endpoint and does not prompt the user to sign in again. The rejected requests repeat about every four minutes for hours.

We run the MCP server at https://api.plori.ai/mcp and observed this from the server side:

  • Session A (copilot-cli/1.0.99-2): the server rejected one bearer token (same fingerprint on every request) 581 times as expired, from 2026-10-19 00:56 UTC to 2026-10-21 06:50 UTC.
  • Session B (copilot-cli): successful MCP pings until 2026-10-20 19:38 UTC, which is one hour after the token was issued (our access tokens live one hour). From 19:42 UTC the server rejected the same expired bearer 82 times, about four minutes apart, until 2026-10-21 05:55 UTC. Between 19:30 and 20:00 UTC our authorization server received no token-endpoint request.

Every rejection is HTTP 401 with:

WWW-Authenticate: Bearer error="invalid_token", resource_metadata="https://api.plori.ai/.well-known/oauth-protected-resource/mcp"

The authorization server advertises grant_types_supported: ["authorization_code", "refresh_token"] and issues rotating refresh tokens when offline_access is requested. The token response sizes we logged before each session match a response that contains a refresh token, so we believe the client held one. We cannot inspect the client's credential store, so this is an inference.

Affected version

copilot-cli/1.0.99-2 (session A). Session B's user agent was copilot-cli without a version.

Steps to reproduce the behavior

  1. Add a remote MCP server whose authorization server issues one-hour access tokens and rotating refresh tokens (offline_access advertised).
  2. Sign in through the CLI's OAuth flow.
  3. Keep the session open past the access token's expiry, with the server connected (background pings or subscriptions running).
  4. Watch the server logs: requests continue with the expired bearer and receive 401 invalid_token; no refresh_token grant reaches the token endpoint.

Expected behavior

On a 401 with error="invalid_token", the client uses its refresh token (RFC 6749 §6), stores the rotated credentials, and retries with the new access token on the active transport. If refresh is not possible, the client tells the user that the server needs authentication again, instead of resending the rejected token.

Additional context

This looks related to #4203, which describes an expired access token at session start forcing interactive sign-in instead of a refresh. Here the token expires during an active session, and the client neither refreshes nor asks for sign-in; it keeps retrying the same token. We are happy to provide more server-side detail (timestamps, request counts) if it helps.

— Plori AI team

Activity

  1. added
    area:mcpMCP server configuration, discovery, connectivity, OAuth, policy, and registry
    and removed on Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:mcpMCP server configuration, discovery, connectivity, OAuth, policy, and registry

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions