Files
TREK/client/vite.config.js
T
jubnl 86129bbfbc feat: migrate OAuth public endpoints to MCP SDK auth handlers
Fixes issue #959 — two bugs causing ChatGPT's custom MCP connector to fail:

1. RFC 9728 path-based PRM: ChatGPT requests
   /.well-known/oauth-protected-resource/mcp (path-aware URL per RFC 9728
   §5). The old TREK handler only registered the base path; requests for
   the path variant fell through to the SPA catch-all and returned HTML.
   mcpAuthMetadataRouter registers the path-aware URL automatically.

2. DCR without scope: ChatGPT never sends scope during Dynamic Client
   Registration (RFC 7591 makes it optional). The old handler returned
   400 for missing scope. clientRegistrationHandler accepts it;
   trekClientsStore.registerClient defaults to ALL_SCOPES when absent,
   and the user still grants only what they approve at the consent UI
   (scopeSelectable=true for DCR clients is unchanged).

Hybrid approach: SDK handles /.well-known, /oauth/authorize (redirect to
consent SPA), and /oauth/register. TREK keeps its own /oauth/token and
/oauth/revoke because SDK clientAuth does plain-text secret comparison
while TREK uses SHA-256 hashing — incompatible without a full clientAuth
rewrite.

SPA consent page renamed /oauth/authorize → /oauth/consent to avoid
routing conflict with the SDK's backend authorize handler now mounted at
that path. Existing URL paths (/oauth/token etc.) are unchanged so
active Claude.ai connections are unaffected.

Other: lazy-init SDK metadata router so getAppUrl() (DB query) is not
called at createApp() time; path-aware mcpAddonGate so only /.well-known
returns 404 when MCP is disabled (previously a blanket middleware blocked
all routes including static files); /api/oauth mounted before the SDK
middleware chain so SPA-facing routes with their own 403 gates are
reached correctly.
2026-05-05 13:01:32 +02:00

87 lines
2.5 KiB
JavaScript

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({
plugins: [
react(),
VitePWA({
registerType: 'autoUpdate',
strategies: 'injectManifest',
srcDir: 'src',
filename: 'sw.ts',
injectManifest: {
globPatterns: ['**/*.{js,css,html,svg,png,woff,woff2,ttf}'],
maximumFileSizeToCacheInBytes: 10 * 1024 * 1024,
},
manifest: {
name: 'TREK \u2014 Travel Planner',
short_name: 'TREK',
description: 'Travel Resource & Exploration Kit',
theme_color: '#111827',
background_color: '#0f172a',
display: 'standalone',
scope: '/',
start_url: '/',
orientation: 'any',
categories: ['travel', 'navigation'],
icons: [
{ src: 'icons/apple-touch-icon-180x180.png', sizes: '180x180', type: 'image/png' },
{ src: 'icons/icon-192x192.png', sizes: '192x192', type: 'image/png' },
{ src: 'icons/icon-512x512.png', sizes: '512x512', type: 'image/png' },
{ src: 'icons/icon-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' },
{ src: 'icons/icon.svg', sizes: 'any', type: 'image/svg+xml' },
],
},
}),
],
build: {
sourcemap: false,
modulePreload: { polyfill: false },
},
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:3001',
changeOrigin: true,
},
'/uploads': {
target: 'http://localhost:3001',
changeOrigin: true,
},
'/ws': {
target: 'http://localhost:3001',
ws: true,
},
'/mcp': {
target: 'http://localhost:3001',
changeOrigin: true,
},
// OAuth 2.1 endpoints handled by backend (SDK authorize handler + token/revoke)
// /oauth/authorize goes to backend so the SDK can redirect to /oauth/consent
// /oauth/consent is served by Vite as a SPA route (no proxy entry needed)
'/oauth/authorize': {
target: 'http://localhost:3001',
changeOrigin: true,
},
'/oauth/token': {
target: 'http://localhost:3001',
changeOrigin: true,
},
'/oauth/register': {
target: 'http://localhost:3001',
changeOrigin: true,
},
'/oauth/revoke': {
target: 'http://localhost:3001',
changeOrigin: true,
},
'/.well-known': {
target: 'http://localhost:3001',
changeOrigin: true,
},
}
}
})