feat(oauth): browser-initiated dynamic client registration (DCR)

Adds an OAuth 2.1 public client registration flow so MCP clients can
self-register via a user-facing consent page instead of requiring manual
setup in Settings.

Server:
- DB migration adds `is_public` and `created_via` columns to oauth_clients
- New GET /api/oauth/register/validate — validates DCR params, returns
  requested scopes; unauthenticated callers get loginRequired flag
- New POST /api/oauth/register — creates a public client, saves consent,
  and redirects with client_id (cookie auth required)
- `authenticateClient` / `refreshTokens` skip secret check for public
  clients (PKCE provides the security guarantee)
- `createOAuthClient` accepts options for isPublic/createdVia; public
  clients store an opaque secret hash instead of a usable secret
- `rotateOAuthClientSecret` blocked on public clients
- `isValidRedirectUri` extracted as a shared helper
- Discovery metadata now advertises registration_endpoint and auth method
  `none`; token/revoke endpoints no longer require client_secret for
  public clients

Client:
- New OAuthRegisterPage (/oauth/register) — loading → optional
  login-required gate → scope selection → done states
- New ScopeGroupPicker component — collapsible groups, indeterminate
  checkboxes, select-all per group or globally
- oauthApi.register.{validate,submit} added to api/client.ts
- apiClient exported so it can be reused outside api/client.ts
- IntegrationsTab tests fixed for new collapsible section structure
- collab_notes fallback changed from undefined to [] in MCP trip tools
This commit is contained in:
jubnl
2026-04-10 05:20:38 +02:00
parent 81a360f9a7
commit 9b1baaf7b8
25 changed files with 739 additions and 235 deletions
+1
View File
@@ -233,6 +233,7 @@ const ar: Record<string, string | { name: string; category: string }[]> = {
'settings.mcp.endpoint': 'نقطة نهاية MCP',
'settings.mcp.clientConfig': 'إعداد العميل',
'settings.mcp.clientConfigHint': 'استبدل <your_token> برمز API من القائمة أدناه. قد يحتاج مسار npx إلى ضبط وفق نظامك (مثلاً C:\\PROGRA~1\\nodejs\\npx.cmd على Windows).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'نسخ',
'settings.mcp.copied': 'تم النسخ!',
'settings.mcp.apiTokens': 'رموز API',
+1
View File
@@ -295,6 +295,7 @@ const br: Record<string, string | { name: string; category: string }[]> = {
'settings.mcp.endpoint': 'Endpoint MCP',
'settings.mcp.clientConfig': 'Configuração do cliente',
'settings.mcp.clientConfigHint': 'Substitua <your_token> por um token de API da lista abaixo. O caminho para o npx pode precisar ser ajustado para o seu sistema (ex.: C:\\PROGRA~1\\nodejs\\npx.cmd no Windows).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Copiar',
'settings.mcp.copied': 'Copiado!',
'settings.mcp.apiTokens': 'Tokens de API',
+1
View File
@@ -181,6 +181,7 @@ const cs: Record<string, string | { name: string; category: string }[]> = {
'settings.mcp.endpoint': 'MCP endpoint',
'settings.mcp.clientConfig': 'Konfigurace klienta',
'settings.mcp.clientConfigHint': 'Nahraďte <your_token> API tokenem ze seznamu níže. Cestu k npx může být nutné upravit pro váš systém (např. C:\\PROGRA~1\\nodejs\\npx.cmd ve Windows).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Kopírovat',
'settings.mcp.copied': 'Zkopírováno!',
'settings.mcp.apiTokens': 'API tokeny',
+1
View File
@@ -228,6 +228,7 @@ const de: Record<string, string | { name: string; category: string }[]> = {
'settings.mcp.endpoint': 'MCP-Endpunkt',
'settings.mcp.clientConfig': 'Client-Konfiguration',
'settings.mcp.clientConfigHint': 'Ersetze <your_token> durch ein API-Token aus der Liste unten. Der Pfad zu npx muss ggf. für dein System angepasst werden (z. B. C:\\PROGRA~1\\nodejs\\npx.cmd unter Windows).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Kopieren',
'settings.mcp.copied': 'Kopiert!',
'settings.mcp.apiTokens': 'API-Tokens',
+1
View File
@@ -249,6 +249,7 @@ const en: Record<string, string | { name: string; category: string }[]> = {
'settings.mcp.endpoint': 'MCP Endpoint',
'settings.mcp.clientConfig': 'Client Configuration',
'settings.mcp.clientConfigHint': 'Replace <your_token> with an API token from the list below. The path to npx may need to be adjusted for your system (e.g. C:\\PROGRA~1\\nodejs\\npx.cmd on Windows).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Copy',
'settings.mcp.copied': 'Copied!',
'settings.mcp.apiTokens': 'API Tokens',
+1
View File
@@ -229,6 +229,7 @@ const es: Record<string, string> = {
'settings.mcp.endpoint': 'Endpoint MCP',
'settings.mcp.clientConfig': 'Configuración del cliente',
'settings.mcp.clientConfigHint': 'Reemplaza <your_token> con un token de la lista de abajo. Es posible que debas ajustar la ruta de npx según tu sistema (p. ej. C:\\PROGRA~1\\nodejs\\npx.cmd en Windows).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Copiar',
'settings.mcp.copied': '¡Copiado!',
'settings.mcp.apiTokens': 'Tokens de API',
+1
View File
@@ -228,6 +228,7 @@ const fr: Record<string, string> = {
'settings.mcp.endpoint': 'Point de terminaison MCP',
'settings.mcp.clientConfig': 'Configuration du client',
'settings.mcp.clientConfigHint': 'Remplacez <your_token> par un token API de la liste ci-dessous. Le chemin vers npx devra peut-être être ajusté selon votre système (ex. C:\\PROGRA~1\\nodejs\\npx.cmd sous Windows).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Copier',
'settings.mcp.copied': 'Copié !',
'settings.mcp.apiTokens': 'Tokens API',
+1
View File
@@ -180,6 +180,7 @@ const hu: Record<string, string | { name: string; category: string }[]> = {
'settings.mcp.endpoint': 'MCP végpont',
'settings.mcp.clientConfig': 'Kliens konfiguráció',
'settings.mcp.clientConfigHint': 'Cserélje ki a <your_token> részt egy API tokenre az alábbi listából. Az npx elérési útját szükség lehet módosítani a rendszeréhez (pl. C:\\PROGRA~1\\nodejs\\npx.cmd Windows-on).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Másolás',
'settings.mcp.copied': 'Másolva!',
'settings.mcp.apiTokens': 'API tokenek',
+1
View File
@@ -180,6 +180,7 @@ const it: Record<string, string | { name: string; category: string }[]> = {
'settings.mcp.endpoint': 'Endpoint MCP',
'settings.mcp.clientConfig': 'Configurazione client',
'settings.mcp.clientConfigHint': 'Sostituisci <your_token> con un token API dalla lista sottostante. Il percorso di npx potrebbe dover essere adattato per il tuo sistema (es. C:\\PROGRA~1\\nodejs\\npx.cmd su Windows).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Copia',
'settings.mcp.copied': 'Copiato!',
'settings.mcp.apiTokens': 'Token API',
+1
View File
@@ -228,6 +228,7 @@ const nl: Record<string, string> = {
'settings.mcp.endpoint': 'MCP-eindpunt',
'settings.mcp.clientConfig': 'Clientconfiguratie',
'settings.mcp.clientConfigHint': 'Vervang <your_token> door een API-token uit de onderstaande lijst. Het pad naar npx moet mogelijk worden aangepast voor jouw systeem (bijv. C:\\PROGRA~1\\nodejs\\npx.cmd op Windows).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Kopiëren',
'settings.mcp.copied': 'Gekopieerd!',
'settings.mcp.apiTokens': 'API-tokens',
+1
View File
@@ -198,6 +198,7 @@ const pl: Record<string, string | { name: string; category: string }[]> = {
'settings.mcp.endpoint': 'Endpoint MCP',
'settings.mcp.clientConfig': 'Konfiguracja klienta',
'settings.mcp.clientConfigHint': 'Zastąp <your_token> tokenem API z listy poniżej. Ścieżka do npx może wymagać dostosowania do Twojego systemu (np. C:\\PROGRA~1\\nodejs\\npx.cmd w systemie Windows).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Kopiuj',
'settings.mcp.copied': 'Skopiowano!',
'settings.mcp.apiTokens': 'Tokeny API',
+1
View File
@@ -228,6 +228,7 @@ const ru: Record<string, string> = {
'settings.mcp.endpoint': 'MCP-эндпоинт',
'settings.mcp.clientConfig': 'Конфигурация клиента',
'settings.mcp.clientConfigHint': 'Замените <your_token> на API-токен из списка ниже. Путь к npx может потребовать настройки для вашей системы (например, C:\\PROGRA~1\\nodejs\\npx.cmd в Windows).',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Копировать',
'settings.mcp.copied': 'Скопировано!',
'settings.mcp.apiTokens': 'API-токены',
+1
View File
@@ -228,6 +228,7 @@ const zh: Record<string, string> = {
'settings.mcp.endpoint': 'MCP 端点',
'settings.mcp.clientConfig': '客户端配置',
'settings.mcp.clientConfigHint': '将 <your_token> 替换为下方列表中的 API 令牌。npx 的路径可能需要根据您的系统进行调整(例如 Windows 上为 C:\\PROGRA~1\\nodejs\\npx.cmd)。',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': '复制',
'settings.mcp.copied': '已复制!',
'settings.mcp.apiTokens': 'API 令牌',
+1
View File
@@ -220,6 +220,7 @@ const zhTw: Record<string, string> = {
'settings.mcp.endpoint': 'MCP 端點',
'settings.mcp.clientConfig': '客戶端配置',
'settings.mcp.clientConfigHint': '將 <your_token> 替換為下方列表中的 API 令牌。npx 的路徑可能需要根據您的系統進行調整(例如 Windows 上為 C:\\PROGRA~1\\nodejs\\npx.cmd)。',
'settings.mcp.clientConfigHintOAuth': 'Replace <your_client_id> and <your_client_secret> with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': '複製',
'settings.mcp.copied': '已複製!',
'settings.mcp.apiTokens': 'API 令牌',