Unified · Split
| @@ -22,7 +22,10 @@ export const protectedResourceMetadataResponse = (organizationId: string | null · 21 unmodified lines | |||
| 22 | resource: resourceUrlFor(organizationId), | 22 | resource: resourceUrlFor(organizationId), |
| 23 | authorization_servers: [AUTHKIT_DOMAIN], | 23 | authorization_servers: [AUTHKIT_DOMAIN], |
| 24 | bearer_methods_supported: ["header"], | 24 | bearer_methods_supported: ["header"], |
| 25 | scopes_supported: [], | 25 | // Spec-faithful clients (OpenCode, mcporter) request exactly what is |
| 26 | // advertised here; without offline_access they get no refresh token and | ||
| 27 | // silently sign out at every access-token expiry. | ||
| 28 | scopes_supported: ["openid", "profile", "email", "offline_access"], | ||
| 26 | }); | 29 | }); |
| 27 | 30 | ||
| 28 | export const authorizationServerMetadataResponse: Effect.Effect<Response> = Effect.tryPromise({ | 31 | export const authorizationServerMetadataResponse: Effect.Effect<Response> = Effect.tryPromise({ |
| @@ -150,7 +150,10 @@ scenario( · 149 unmodified lines | |||
| 150 | resource: new URL("/mcp", target.baseUrl).toString(), | 150 | resource: new URL("/mcp", target.baseUrl).toString(), |
| 151 | authorization_servers: [expect.any(String)], | 151 | authorization_servers: [expect.any(String)], |
| 152 | bearer_methods_supported: ["header"], | 152 | bearer_methods_supported: ["header"], |
| 153 | scopes_supported: [], | 153 | // offline_access MUST stay advertised: spec-faithful clients request |
| 154 | // exactly this list, and it is what earns them a refresh token (the | ||
| 155 | // OpenCode daily re-auth bug). | ||
| 156 | scopes_supported: ["openid", "profile", "email", "offline_access"], | ||
| 154 | }); | 157 | }); |
| 155 | 158 | ||
| 156 | // The advertised server must itself be discoverable — that is what lets | 159 | // The advertised server must itself be discoverable — that is what lets |