Oauth missing scopes after Reconnect

Hello team, we are observing strange behavior during the reconnection flow of the application.
Scenario #1

  1. We create a new Connector. ChatGPT parses our well-known endpoints to retrieve information about available endpoints and scopes.
  2. ChatGPT calls the /register endpoint to create a new client (Client Dynamic Registration), and we return the client_id along with additional client information.
  3. ChatGPT calls the /authorize endpoint with client_id, redirect_uri, scope, etc.
  4. Example request:
  5. https://my-domain/oauth/authorize?response_type=code&client_id=811703c8-c50a-4a49-a119-0035430610cd&redirect_uri=https%3A%2F%2Fchatgpt.com%2Fconnector_platform_oauth_redirect&state=oauth_s_691b55f5b11481919ddp59nge4998443f&scope=worker%3Aread+time-off%3Aread+time-off%3Awrite+contracts%3Aread+people%3Aread&code_challenge=wQiZOt66Pv46ulV0WG8K9vqHiy1VcPaSmeEb5LqtD6Y&code_challenge_method=S256&resource=https%3A%2F%2Fmy-domain%2Fmcp
  6. The user reaches the consent page, approves the requested scopes, and we redirect back to the redirect_uri with a code.
  7. ChatGPT calls the /token endpoint to exchange the authorization code using the code_verifier, and we return an access_token and a refresh_token.
  8. Everything works correctly and the user can start using our MCP server.

Scenario #2

  1. The user goes to the Apps & Connector page and clicks Disconnect for our application.
  2. They click Connect again, and a popup appears to reconnect our Connector.
  3. After clicking Continue, ChatGPT calls /authorize but without the scope parameter.
  4. Example request:
  5. https://my-domain/oauth/authorize?response_type=code&client_id=811703c8-c50a-4a49-a119-0035430610cd&redirect_uri=https%3A%2F%2Fchatgpt.com%2Fconnector_platform_oauth_redirect&state=oauth_s_691b57560b648191a5a85lt8e30e0894&code_challenge=usJfT28XGmDtSalaQQgcvouUG95K5jDvwNiL21j8u5o&code_challenge_method=S256&resource=https%3A%2F%2Fmy-domain%2Fmcp

We return an error because scope must not be empty, per OAuth 2 specification.

Scenario #3
This scenario starts the same way as Scenario #1:

  1. New Connector created, ChatGPT fetches well-known endpoints and scopes.
  2. ChatGPT calls /register.
  3. ChatGPT calls /authorize with scopes.
    However:
  4. We do not allow consent, close the tab, and open a new ChatGPT tab.
  5. The Connector entry exists but is not connected, so we click Connect again.
  6. The same popup appears (as in Scenario #2), but this time ChatGPT does include scopes in the /authorize request.
    This is strange:
  • The UI flow is identical to Scenario #2.
  • In Scenario #2, scopes are missing.
  • In Scenario #3, scopes are present.

Debugging Notes

  • Our logs show no backend errors.
  • Initially, ChatGPT correctly calls the well-known endpoints to retrieve available scopes and endpoints.
  • During the reconnection attempt in Scenario #2, ChatGPT does not call any endpoints that would allow it to retrieve scopes again.
  • As per OAuth 2.0, only the well-known endpoint should store information about available scopes.
  • We suspect this may be related to Developer Mode, but this is only an assumption.

Problem
According to the OAuth 2.0 specification, the /authorize endpoint must always be called with a scope parameter that lists the permissions the application is requesting on behalf of the user.
However, ChatGPT sometimes sends the /authorize request without scopes during a reconnect attempt.

Thanks for the detailed write-up! Hopefully I can help clarify some missing points.
When a connector is reconnected, ChatGPT relies on cached metadata from the provider’s discovery endpoints and may not re-request scopes if refresh token support is not clearly advertised. If offline_access (or your equivalent refresh scope) is missing or not granted, the authorize request can end up being sent without scopes, which then fails per OAuth spec or later causes silent expiry.

A few things to double-check on your side:

  • Ensure your .well-known/openid-configuration or .well-known/oauth-authorization-server explicitly advertises offline_access (or the refresh token scope you expect) in scopes_supported.
  • Confirm your IdP is configured to issue refresh tokens for this client.
  • After updating metadata or IdP settings, delete and recreate the connector so ChatGPT refetches the discovery document.

This is also called out in our docs here:
https://help.openai.com/en/articles/12584461-developer-mode-apps-and-full-mcp-connectors-in-chatgpt-beta#h_73fb68ebd5

We agree the reconnect behavior is confusing, and we’re tracking improvements here so scope handling is more consistent across initial connect and reconnect flows.