Wiki/bridge/docs/baserow-auth.md
Corentin JOGUET 445dda260a feat(bridge): add Baserow user JWT auto-login for metadata endpoints — Patch 031
Service account pattern resolves 401 PERMISSION_DENIED on Baserow metadata
endpoints (/api/database/views/table/:id/, /api/database/tables/:id/) which
reject DB tokens. A dedicated Baserow user account logs in via token-auth,
JWT cached in memory with mutex-protected refresh before expiry.

Fallback graceful: if BASEROW_USER_EMAIL/PASSWORD absent, CRUD rows still work,
metadata endpoints return 500 BASEROW_USER_AUTH_NOT_CONFIGURED.

417 tests pass (was 392, +25). 0 TS errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 14:44:55 +02:00

4.4 KiB

Baserow Authentication — Bridge Service

Pourquoi deux types de tokens

Baserow expose deux mecanismes d'authentification aux comportements differents :

Type Header Droits Usages
DB token Token brg_* CRUD rows uniquement listRows, createRow, updateRow, deleteRow
User JWT JWT eyJ... Toutes les routes API Metadata : listViews, getTable, resolveTableIds

Le DB token (BASEROW_API_TOKEN) est suffisant pour 90% des cas mais Baserow renvoie 401 PERMISSION_DENIED sur les endpoints metadata. Ce n'est pas un bug : c'est la conception Baserow qui distingue DB tokens (CRUD rows) des user sessions (lecture full-API).

Le bridge utilise donc les deux :

  • DB token : routes /api/database/rows/table/:id/ — toujours actif
  • User JWT : routes /api/database/views/table/:id/, /api/database/tables/:id/ — actif si BASEROW_USER_EMAIL + BASEROW_USER_PASSWORD sont configures

API Baserow — endpoints JWT

Source : docs.baserow.io + github.com/code-watch/baserow/blob/master/docs/getting-started/api.md

Login

POST /api/user/token-auth/
Content-Type: application/json

{ "username": "email@example.com", "password": "..." }

Reponse :

{ "token": "eyJ..." }

Le JWT est valide 60 minutes (valeur par defaut Baserow, configurable cote serveur).

Refresh

POST /api/user/token-refresh/
Content-Type: application/json

{ "token": "eyJ..." (token courant) }

Reponse :

{ "token": "eyJ..." (nouveau token) }

Header d'autorisation

Authorization: JWT eyJ...

Note : le prefixe est JWT, pas Bearer ni Token.

Creer le compte service Baserow

  1. Ouvrir http://<baserow-host>/admin/users/
  2. Cliquer "Add user"
  3. Remplir :
    • Email : bridge-svc@interne.local (ou equivalent interne)
    • Password : generer un mot de passe fort (min 16 chars, stocker dans Vault ou secret manager)
    • Is active : oui
    • Is staff : non (pas besoin d'admin)
  4. Ajouter ce user aux groupes (workspaces) ou il doit lire les tables
    • Permission "Member" suffit pour lire views + tables
  5. Verifier : curl -X POST http://baserow/api/user/token-auth/ -d '{"username":"bridge-svc@...","password":"..."}'

Variables d'environnement

# Requis pour activer le JWT manager
BASEROW_USER_EMAIL=bridge-svc@interne.local
BASEROW_USER_PASSWORD=generated-strong-password

# Optionnel — refresh le JWT N secondes avant son expiration (defaut 60)
BASEROW_JWT_REFRESH_MARGIN=60

Si ces variables sont absentes, le bridge continue a fonctionner pour les CRUD rows. Les routes views renvoient 500 BASEROW_USER_AUTH_NOT_CONFIGURED.

Verification que ca marche

Via le health endpoint

curl -s http://localhost:4000/api/health
# { "status": "ok", "service": "bridge", "version": "0.1.0" }

Via la route views

curl -s \
  -H "Authorization: Bearer brg_<votre-token>" \
  "http://localhost:4000/api/v1/views/table/personne"
# { "data": [...], "total": N }

Avant Patch 031, cette route retournait 401 de Baserow. Apres Patch 031 avec JWT configure, elle retourne les vues de la table.

Verifier les logs au boot

INFO: Baserow user JWT manager enabled (email: bridge-svc@interne.local)

Si vous voyez a la place :

INFO: Baserow user JWT manager disabled — metadata endpoints will return 503 if called

c'est que BASEROW_USER_EMAIL ou BASEROW_USER_PASSWORD est absent.

Architecture interne

getToken() appel ─► BaserowJwtManagerImpl
  ├─ token cache frais ? → retour immediat
  ├─ token bientot expire ? → POST /api/user/token-refresh/
  │   └─ echec ? → fallback POST /api/user/token-auth/
  └─ pas de token ? → POST /api/user/token-auth/

Mutex : si 10 appels simultanes → 1 seul login/refresh, les 9 autres attendent.

BaserowClient.listViewsWithJwt(tableId, jwt) utilise Authorization: JWT <jwt> vers Baserow.

Bonnes pratiques securite

  • Le password est remplace par *** dans les logs (voir baserow-jwt-manager.ts, appels this.logger.error)
  • Le JWT reste en memoire uniquement (pas de Redis, pas de fichier disque)
  • Le JWT n'est pas retransmis dans les reponses HTTP du bridge vers les clients
  • En cas de rotation du mot de passe Baserow : redemarrer le bridge (re-login au premier appel)
  • Stocker BASEROW_USER_PASSWORD dans un secret manager (Vault, Docker secrets, k8s Secret)