fix: 404 JSON + open CORS for all /.well-known/* paths

ChatGPT probes /.well-known/openid-configuration and the RFC 8414
path-suffixed form /.well-known/oauth-authorization-server/mcp before
(or instead of) following the RFC 9728 WWW-Authenticate chain.
Both returned 200 HTML from the SPA catch-all, which clients can't
parse as JSON — ChatGPT reported 'does not implement OAuth'.

Two fixes:
- Extend open-CORS pre-middleware from /.well-known/oauth-* to all
  /.well-known/* so browser-based probes aren't CORS-blocked
- Add a 404 JSON catch-all for /.well-known/* paths the SDK metadata
  router doesn't handle, placed before the SPA catch-all
This commit is contained in:
jubnl
2026-05-05 14:16:28 +02:00
parent af10ab1c93
commit 001cc6431b
+12 -1
View File
@@ -100,10 +100,12 @@ export function createApp(): express.Application {
// with Bearer tokens from any origin. /oauth/register and /oauth/authorize need it for
// browser-based DCR/authorization preflights — the global cors({ origin: false }) would
// answer OPTIONS without Access-Control-Allow-Origin before the SDK's own cors() runs.
// All /.well-known/* paths get open CORS so clients probing openid-configuration or the
// RFC 8414 path-suffixed AS metadata form don't get CORS-blocked (they get 404 JSON instead).
app.use(
(req: Request, _res: Response, next: NextFunction) => {
if (
req.path.startsWith('/.well-known/oauth-') ||
req.path.startsWith('/.well-known/') ||
req.path === '/oauth/register' ||
req.path === '/oauth/authorize' ||
req.path === '/mcp'
@@ -428,6 +430,15 @@ export function createApp(): express.Application {
app.get('/mcp', mcpHandler);
app.delete('/mcp', mcpHandler);
// Return 404 JSON for any /.well-known/* path the SDK metadata router doesn't handle.
// Without this, the SPA catch-all serves HTML — clients probing
// /.well-known/openid-configuration or the RFC 8414 path-suffixed AS metadata URL
// receive a 200 HTML response they can't parse as JSON, causing "does not implement OAuth".
app.use((req: Request, res: Response, next: NextFunction) => {
if (req.path.startsWith('/.well-known/')) return res.status(404).json({ error: 'not_found' });
next();
});
// Production static file serving
if (process.env.NODE_ENV === 'production') {
const publicPath = path.join(__dirname, '../public');