Files
telegram-gateway/AUTH.md
Gabriel Radureau 07115e3162
Some checks failed
Docker Build / build-and-push-image (push) Failing after 18s
Phase 1.5 — auth layer (Redis sessions, allowlist, requireAuth)
Adds an authentication layer in front of the bot handlers :

- Auth handler on the principal bot (@arcodange_factory_bot, slug
  factory) parses /start, /auth <code>, /whoami, /logout. On a
  successful /auth, the message containing the code is best-effort
  deleted from the user's chat (replay defense).
- Redis-backed sessions (key tg-gw:auth:<from.id>, TTL 24h, configurable
  via AUTH_SESSION_TTL). Constant-time secret compare via crypto/subtle.
- ALLOWED_USERS env (CSV of Telegram user IDs) — silent-drops anyone
  not in the list before the auth gate runs.
- New per-bot field 'requireAuth' (pointer-bool). Default = true (secure
  by default). Auto-forced to false for handler=auth (chicken-and-egg).
- Server gates: allowlist first, then requireAuth before handler dispatch.
- Fail-at-startup if a bot is configured with handler=auth or
  requireAuth: true while AUTH_SECRET is unset.

Design: factory/docs/adr/20260509-telegram-gateway-auth.md (in factory PR).
User docs: AUTH.md (new), HOWTO_ADD_BOT.md (Cas 2 updated for default
true and gated flow).

New deps: github.com/redis/go-redis/v9.

Refs ~/.claude/plans/pour-les-notifications-on-inherited-seal.md § Phase 1.5.
2026-05-09 13:56:30 +02:00

4.7 KiB

← README · HOWTO_ADD_BOT · Authentification

Détails de design : factory ADR 20260509 — telegram-gateway auth

Authentification

Le gateway est protégé en deux couches :

  1. Allowlist (ALLOWED_USERS, optionnelle) — filtre la liste des Telegram user IDs autorisés à parler à n'importe quel bot. Hors-liste : silent drop, le bot ne répond rien (l'inconnu ne sait même pas que le bot existe).
  2. Session /auth — par défaut, tous les bots du gateway exigent une session active (requireAuth: true par défaut). Pour ouvrir une session, il faut DM @arcodange_factory_bot avec /auth <code>. Une session dure 24 h (configurable via AUTH_SESSION_TTL).

Côté utilisateur

1. Ouvrir une session

  1. Sur Telegram, ouvre @arcodange_factory_bot.
  2. Envoie /auth <code> (le code t'a été partagé par l'admin du gateway).
  3. Le bot répond ✅ Authentifié pour 24 h. Ton message contenant le code est automatiquement supprimé du chat (replay defense).
  4. Tu peux maintenant DM les autres bots normalement.

2. Vérifier sa session

/whoami

Réponse type : user=123456 : ✅ authentifié, reste 23h59m. ou user=123456 : non authentifié..

3. Fermer une session

/logout

4. Quand un bot répond 🔒 Authentifie-toi …

Ta session a expiré (TTL dépassé) ou tu n'as jamais fait /auth. Va sur @arcodange_factory_bot, refais /auth <code>.

Côté opérateur

Définir / changer le code AUTH_SECRET

# Choisir un code fort (ex : openssl rand -hex 16)
SECRET='<chosen-code>'

kubectl -n telegram-gateway patch secret telegram-gateway-bots --type=json -p="[
  {\"op\":\"replace\",\"path\":\"/data/AUTH_SECRET\",\"value\":\"$(echo -n "$SECRET" | base64)\"}
]"

# Restart pour reload du Secret
kubectl -n telegram-gateway rollout restart deploy/telegram-gateway

Rotation : changer AUTH_SECRET invalide les futurs /auth mais pas les sessions Redis déjà ouvertes (elles vivent jusqu'à leur TTL). Pour invalider tout : kubectl exec -n tools redis-0 -- redis-cli --scan --pattern 'tg-gw:auth:*' | xargs -I{} kubectl exec -n tools redis-0 -- redis-cli DEL {}.

Définir / changer l'allowlist

kubectl -n telegram-gateway patch secret telegram-gateway-bots --type=json -p="[
  {\"op\":\"replace\",\"path\":\"/data/ALLOWED_USERS\",\"value\":\"$(echo -n '12345,67890' | base64)\"}
]"
kubectl -n telegram-gateway rollout restart deploy/telegram-gateway

Pour désactiver l'allowlist (ouvrir à tout Telegram user en allowlist) :

kubectl -n telegram-gateway patch secret telegram-gateway-bots --type=json -p='[
  {"op":"remove","path":"/data/ALLOWED_USERS"}
]'
kubectl -n telegram-gateway rollout restart deploy/telegram-gateway

Inspecter une session Redis

USER_ID=123456
kubectl exec -n tools redis-0 -- redis-cli GET   "tg-gw:auth:$USER_ID"   # → "1" ou (nil)
kubectl exec -n tools redis-0 -- redis-cli TTL   "tg-gw:auth:$USER_ID"   # → secondes restantes
kubectl exec -n tools redis-0 -- redis-cli DEL   "tg-gw:auth:$USER_ID"   # → forcer logout

Rendre un bot public (opt-out de l'auth)

Dans chart/values.yaml, ajouter requireAuth: false au bot concerné :

bots:
  statusbot:
    handler: echo
    requireAuth: false   # bot public, pas de session requise

Cas spécial : handler: auth (le bot principal factory) force toujours requireAuth: false automatiquement (sinon l'auth elle-même serait inaccessible — chicken-and-egg).

Limites connues

  • Pas de TOTP / OTP rotatif — un code partagé suffit pour cet usage privé. À reconsidérer si on ouvre à plus d'utilisateurs.
  • Pas de rate-limit sur /auth — l'ALLOWED_USERS joue le rôle de garde-fou. Avec un code fort (≥ 128 bits), le bruteforce est inutile dans la fenêtre de TTL.
  • Sessions invalidées si Redis tombe — fail-closed : tous les bots gated répondent 🔒 jusqu'à ce que Redis revienne. Acceptable.
  • from.id-based, pas IP-based — Telegram n'expose pas l'IP du user au bot. Une session couvre tous les devices d'un même compte Telegram, ce qui est le comportement attendu.

Chemin de migration vers Vault (Phase 2+)

Aujourd'hui, AUTH_SECRET et ALLOWED_USERS vivent dans un Secret k8s créé via kubectl create secret. À terme, ils basculeront dans Vault (toggle vault.enabled: true dans chart/values.yaml, provisionner kvv2/telegram-gateway/config). Le code n'a pas à changer — envFrom: secretRef consomme indifféremment un Secret manuel ou un Secret produit par VaultStaticSecret.