5.1 KiB
baserow-mcp-oauth-fix — sidecar OAuth devant Baserow (28/07/2026)
Statut : PRODUCTION. Reverse-proxy DSM bascule 3888->3887 le 28/07/2026, valide en public (well-known/register/app web/API tous 200/302 comme attendu). Connecteur claude.ai a reconnecter cote Nabil si pas deja fait.
Probleme
Connecteur Claude.ai vers Baserow MCP (https://baserow.bolbol.tn/mcp/<token>/sse) :
« Impossible de s'inscrire aupres du service de connexion de Baserow ».
Cause : meme piege que mcp-vps.md/mcp-nas — Claude.ai sonde systematiquement
/.well-known/oauth-authorization-server, /.well-known/oauth-protected-resource et
POST /register a l'ajout d'un connecteur MCP personnalise, meme quand le serveur
cible n'a besoin d'aucune auth (la vraie protection Baserow = le token secret deja
dans l'URL /mcp/<token>/sse). Baserow (Caddy + Nuxt) renvoie 404 (page Nuxt
generique, pas une 404 backend) sur ces 3 routes → echec du handshake connecteur.
Difference avec mcp-vps/mcp-nas : ceux-la sont du code Python maison, patchable directement. Baserow est l'image officielle (watchtower la met a jour) — impossible de patcher son code source sans que ca saute au prochain rebuild/update.
Fix
Sidecar devant Baserow, sans toucher a l'image Baserow :
/volume1/docker/baserow-oauth-stub (2 containers, reseau n8n uniquement) :
- baserow-oauth-app (Starlette/uvicorn, build local, pas de port publie) :
/register,/authorize,/token— meme pattern PKCE quelinux_mcp_server.py(mcp-vps),CLIENT_ID = claude-baserow-mcp, tokens jamais verifies ailleurs (la seule vraie protection reste le token dans l'URL Baserow). - baserow-oauth-proxy (nginx:alpine, port 3887→80, reseau
n8n) :/.well-known/oauth-authorization-serveret/.well-known/oauth-protected-resource(/*)→ JSON statique (fichiers montes en volume, pas de logique dynamique necessaire)/register,/authorize,/token→ proxy versbaserow-oauth-app:8080location /(tout le reste : app web, API,/ws/*,/mcp/*/sse) → proxy transparent versbaserow:80(alias Docker du container Baserow sur le reseaun8n), avec support WebSocket (map $http_upgrade $connection_upgrade) et SSE (proxy_buffering off,proxy_read_timeout 3600s,chunked_transfer_encoding on).
Gotcha reseau (couteux a redecouvrir)
Premiere tentative : 2 services sur un reseau default cree par le compose (nouveau
bridge custom) + le service nginx en plus sur n8n. Resultat : ping fonctionne
entre les 2 containers, mais toute connexion TCP (nc, wget, proxy_pass) time out
en silence (502/504 selon le point de test) — alors que Baserow lui-meme (deja sur
n8n) passait sans probleme. Hypothese : regle firewall (crowdsec-firewall-bouncer
ou iptables DOCKER-USER) qui n'autorise le trafic TCP inter-conteneurs que sur les
reseaux Docker deja connus/etablis (n8n), pas sur un reseau tout juste cree.
Fix : mettre les 2 services UNIQUEMENT sur le reseau externe n8n (pas de reseau
default supplementaire) — resout immediatement le probleme, ping ET TCP passent.
A retenir pour tout futur sidecar : privilegier un reseau externe deja peuple plutot
qu'un nouveau bridge, si un blocage TCP-mais-pas-ICMP apparait entre 2 conteneurs.
Tests de validation (28/07/2026)
Tous compares en baseline (direct port 3888, bypass total du sidecar) vs via le proxy (port 3887) :
| Test | Baseline 3888 | Via proxy 3887 |
|---|---|---|
/.well-known/oauth-authorization-server |
404 (Baserow) | 200 JSON statique |
/.well-known/oauth-protected-resource |
404 (Baserow) | 200 JSON statique |
POST /register |
404 (Baserow) | 201, client_id: claude-baserow-mcp |
GET /authorize + PKCE S256 → POST /token |
n/a | 200, access_token + refresh_token |
GET /mcp/<token>/sse (bon Host header) |
200, event endpoint |
200, event endpoint identique |
GET / (app web) |
302 (redirect login) | 302 identique |
GET /api/_health/ |
200 | 200 identique |
Upgrade WebSocket /ws/core/ |
101 Switching Protocols | 101 identique |
Piege methodologique note en passant : tester /mcp/<token>/sse en curl direct
sur le port 3888 SANS forcer Host: baserow.bolbol.tn renvoie un faux-negatif (404
JSON generique Nuxt) — le Caddyfile de Baserow route /api/* /ws/* /mcp/* /assistant/*
vers le backend uniquement si l'expression @is_baserow_tool matche BASEROW_PUBLIC_URL
sur le Host recu ; sinon fallback silencieux vers le frontend Nuxt qui 404 proprement.
Toujours forcer le bon Host en test local.
Action manuelle (faite le 28/07/2026)
Reverse-proxy DSM baserow.bolbol.tn bascule 3888 → 3887. Verifie en public
immediatement apres : well-known x2, register, app web (302), API (200) tous
identiques au comportement attendu. Reversible en 10 secondes (remettre 3888)
si jamais un probleme apparait plus tard.
Fichiers
/volume1/docker/baserow-oauth-stub/ : oauth_app.py, Dockerfile, nginx.conf,
oauth-authorization-server.json, oauth-protected-resource.json, docker-compose.yml
(miroir complet pousse dans ce commit, sous common/baserow-oauth-stub/).