Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions apps/web/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ const nextConfig: NextConfig = {
},
],
},
{
// The OAuth consent page must never be framed (clickjacking an Allow).
// middleware.ts also sends frame-ancestors 'none' for it.
source: '/oauth/authorize',
headers: [{ key: 'X-Frame-Options', value: 'DENY' }],
},
{
// `curl -fsSL https://pairux.com/install.sh | sh`: serve the installer
// as a shell script so browsers show it instead of guessing.
Expand All @@ -91,6 +97,22 @@ const nextConfig: NextConfig = {
];
},

// The path-suffixed discovery forms some MCP clients try first
// (/.well-known/oauth-protected-resource/api/v1/mcp, RFC 9728 §3.1) answer
// the same documents as the bare paths (lib/mcp-oauth.ts).
rewrites() {
return [
{
source: '/.well-known/oauth-protected-resource/:path*',
destination: '/.well-known/oauth-protected-resource',
},
{
source: '/.well-known/oauth-authorization-server/:path*',
destination: '/.well-known/oauth-authorization-server',
},
];
},

// Redirects
redirects() {
return [
Expand Down
16 changes: 16 additions & 0 deletions apps/web/src/app/.well-known/oauth-authorization-server/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NextResponse } from 'next/server';
import { authorizationServerMetadata, CORS_HEADERS } from '@/lib/mcp-oauth';

export const dynamic = 'force-dynamic';

// RFC 8414 authorization server metadata. The [...path] sibling answers the
// path-suffixed form some clients try first.
export function GET() {
return NextResponse.json(authorizationServerMetadata(), {
headers: { ...CORS_HEADERS, 'cache-control': 'public, max-age=3600' },
});
}

export function OPTIONS() {
return new NextResponse(null, { status: 204, headers: CORS_HEADERS });
}
16 changes: 16 additions & 0 deletions apps/web/src/app/.well-known/oauth-protected-resource/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NextResponse } from 'next/server';
import { CORS_HEADERS, protectedResourceMetadata } from '@/lib/mcp-oauth';

export const dynamic = 'force-dynamic';

// RFC 9728 protected-resource metadata for the MCP server at /api/mcp. The
// [...path] sibling answers the path-suffixed form (/.well-known/oauth-protected-resource/api/mcp).
export function GET() {
return NextResponse.json(protectedResourceMetadata(), {
headers: { ...CORS_HEADERS, 'cache-control': 'public, max-age=3600' },
});
}

export function OPTIONS() {
return new NextResponse(null, { status: 204, headers: CORS_HEADERS });
}
Loading
Loading