What
Saddle's OAuth discovery documents never advertise offline_access in
scopes_supported. OpenAI's current guidance says ChatGPT inspects a provider's
discovery metadata for exactly that scope before relying on refresh tokens.
Why it matters
From Developer mode and MCP apps in ChatGPT
(OpenAI Help Center, updated 2026-08-22):
Verify the provider's discovery .well-known endpoints
(.well-known/openid-configuration or .well-known/oauth-authorization-server)
list offline_access (or your provider's equivalent) in scopes_supported or a
similar capability field. If offline_access (or the equivalent refresh token
scope) is not advertised or refresh tokens are not being issued, enable offline
or refresh access in your provider's admin console [...] then recreate the app
so ChatGPT fetches the updated metadata.
If OAuth is configured without offline_access, ChatGPT may lose access after
the original authorization expires because refresh-token renewal may be
unavailable, and users may need to reauthenticate.
With ACCESS_TTL = 3600, the failure mode would be a ChatGPT connector that works
for one hour and then dies, with reconnecting as the only remedy — which is
indistinguishable from the "connected but broken" reports we already field.
Current state
Saddle_OAuth::SCOPES = array( 'saddle:read', 'saddle:write', 'saddle:admin' )
(includes/oauth/class-saddle-oauth.php:49)
scopes_supported is fed straight from that constant
(includes/oauth/class-saddle-oauth-discovery.php:333 and :361)
offline_access appears nowhere in the tree
- Refresh tokens ARE implemented and issued unconditionally
(grant_refresh_token(), class-saddle-oauth-endpoints.php:278)
grant_types_supported DOES advertise refresh_token
(class-saddle-oauth-discovery.php:364)
ACCESS_TTL = 3600, REFRESH_TTL = 2592000 (class-saddle-oauth-store.php:50,55)
Confidence
Suspected, not confirmed. OpenAI frames this as OpenID Connect guidance, and
Saddle is a plain OAuth 2.1 authorization server that returns a refresh token
whether or not the scope was requested. ChatGPT may well accept it regardless.
Nobody has reported an hour-long ChatGPT session dying, but we have few ChatGPT
connector users and that symptom would look like a generic disconnect.
Proposed fix
Cheap and low-risk, because the refresh machinery already works:
- Advertise
offline_access in scopes_supported (discovery only — do not add
it to SCOPES, which is the tier-clamp set and must stay exactly three).
- Accept
offline_access in an authorization request as a no-op: never let
it reach get_tier(), never map it to a capability. It must not widen access.
- Pin both in tests: the discovery document lists it, and a grant carrying it
resolves to the same tier as one without it.
The scope clamp (min(site tier, granted scope)) must be provably untouched —
that is the load-bearing OAuth invariant.
Alternative
Verify empirically first: connect ChatGPT to a Saddle site and confirm whether the
connection survives past the 1-hour access-token expiry. Needs a real ChatGPT
Business/Enterprise account and an hour of waiting.
Refs the docs sweep on plugpress.co that surfaced this.
What
Saddle's OAuth discovery documents never advertise
offline_accessinscopes_supported. OpenAI's current guidance says ChatGPT inspects a provider'sdiscovery metadata for exactly that scope before relying on refresh tokens.
Why it matters
From Developer mode and MCP apps in ChatGPT
(OpenAI Help Center, updated 2026-08-22):
With
ACCESS_TTL = 3600, the failure mode would be a ChatGPT connector that worksfor one hour and then dies, with reconnecting as the only remedy — which is
indistinguishable from the "connected but broken" reports we already field.
Current state
Saddle_OAuth::SCOPES=array( 'saddle:read', 'saddle:write', 'saddle:admin' )(
includes/oauth/class-saddle-oauth.php:49)scopes_supportedis fed straight from that constant(
includes/oauth/class-saddle-oauth-discovery.php:333and:361)offline_accessappears nowhere in the tree(
grant_refresh_token(),class-saddle-oauth-endpoints.php:278)grant_types_supportedDOES advertiserefresh_token(
class-saddle-oauth-discovery.php:364)ACCESS_TTL = 3600,REFRESH_TTL = 2592000(class-saddle-oauth-store.php:50,55)Confidence
Suspected, not confirmed. OpenAI frames this as OpenID Connect guidance, and
Saddle is a plain OAuth 2.1 authorization server that returns a refresh token
whether or not the scope was requested. ChatGPT may well accept it regardless.
Nobody has reported an hour-long ChatGPT session dying, but we have few ChatGPT
connector users and that symptom would look like a generic disconnect.
Proposed fix
Cheap and low-risk, because the refresh machinery already works:
offline_accessinscopes_supported(discovery only — do not addit to
SCOPES, which is the tier-clamp set and must stay exactly three).offline_accessin an authorization request as a no-op: never letit reach
get_tier(), never map it to a capability. It must not widen access.resolves to the same tier as one without it.
The scope clamp (
min(site tier, granted scope)) must be provably untouched —that is the load-bearing OAuth invariant.
Alternative
Verify empirically first: connect ChatGPT to a Saddle site and confirm whether the
connection survives past the 1-hour access-token expiry. Needs a real ChatGPT
Business/Enterprise account and an hour of waiting.
Refs the docs sweep on plugpress.co that surfaced this.