Gateway
Authentification par proxy de confiance
Quand l’utiliser
Utilisez le mode d’authentification trusted-proxy lorsque :
- Vous exécutez OpenClaw derrière un proxy sensible à l’identité (Pomerium, Caddy + OAuth, nginx + oauth2-proxy, Traefik + authentification transférée).
- Votre proxy gère toute l’authentification et transmet l’identité utilisateur via des en-têtes.
- Vous êtes dans un environnement Kubernetes ou conteneurisé où le proxy est le seul chemin vers le Gateway.
- Vous rencontrez des erreurs WebSocket
1008 unauthorizedparce que les navigateurs ne peuvent pas transmettre de jetons dans les charges utiles WS.
Quand NE PAS l’utiliser
- Si votre proxy n’authentifie pas les utilisateurs (simple terminaison TLS ou équilibreur de charge).
- S’il existe un chemin vers le Gateway qui contourne le proxy (ouvertures de pare-feu, accès au réseau interne).
- Si vous n’êtes pas sûr que votre proxy supprime/remplace correctement les en-têtes transférés.
- Si vous avez seulement besoin d’un accès personnel pour un seul utilisateur (envisagez Tailscale Serve + loopback pour une configuration plus simple).
Fonctionnement
Le proxy authentifie l’utilisateur
Votre proxy inverse authentifie les utilisateurs (OAuth, OIDC, SAML, etc.).
Le proxy ajoute un en-tête d’identité
Le proxy ajoute un en-tête contenant l’identité de l’utilisateur authentifié (par exemple, x-forwarded-user: nick@example.com).
Le Gateway vérifie la source de confiance
OpenClaw vérifie que la requête provient d’une IP de proxy de confiance (configurée dans gateway.trustedProxies).
Le Gateway extrait l’identité
OpenClaw extrait l’identité utilisateur depuis l’en-tête configuré.
Autoriser
Si toutes les vérifications réussissent, la requête est autorisée.
Comportement d’appairage de Control UI
Lorsque gateway.auth.mode = "trusted-proxy" est actif et que la requête passe les vérifications trusted-proxy, les sessions WebSocket de Control UI peuvent se connecter sans identité d’appairage d’appareil.
Implications de portée :
- Les sessions WebSocket de Control UI sans appareil se connectent, mais ne reçoivent par défaut aucune portée opérateur. OpenClaw vide la liste des portées demandées en
[]afin qu’une session qui n’est pas liée à un appareil/jeton appairé approuvé ne puisse pas déclarer elle-même des autorisations. - Si des méthodes échouent avec
missing scopeaprès une connexion WebSocket réussie, utilisez HTTPS afin que le navigateur puisse générer une identité d’appareil et terminer l’appairage. Consultez HTTP non sécurisé de Control UI. - Bris de glace uniquement :
gateway.controlUi.dangerouslyDisableDeviceAuth=trueconserve les portées demandées même sans identité d’appareil. Il s’agit d’un affaiblissement grave de la sécurité ; rétablissez rapidement la configuration. Consultez HTTP non sécurisé de Control UI.
Plafonnement des portées par le proxy inverse :
- Si votre proxy envoie
x-openclaw-scopessur la requête de mise à niveau WebSocket de Control UI, OpenClaw limite les portées de session à l’intersection des portées demandées et des portées déclarées. Cet en-tête n’accorde pas de portées ; il réduit uniquement ce que la session peut détenir.
Implications :
- L’appairage n’est plus la barrière principale pour l’accès à Control UI dans ce mode.
- La politique d’authentification de votre proxy inverse et
allowUsersdeviennent le contrôle d’accès effectif. - Gardez l’entrée du Gateway limitée aux seules IP de proxy de confiance (
gateway.trustedProxies+ pare-feu).
Les clients WebSocket personnalisés ne sont pas des sessions Control UI. gateway.controlUi.dangerouslyDisableDeviceAuth n’accorde pas de portées aux clients arbitraires client.mode: "backend" ou de forme CLI. Les automatisations personnalisées doivent utiliser l’identité/l’appairage d’appareil, le chemin d’aide backend local direct réservé client.id: "gateway-client", ou le plugin RPC HTTP admin lorsqu’une surface de requête/réponse HTTP convient mieux.
Configuration
{ gateway: { // Trusted-proxy auth expects requests from a non-loopback trusted proxy source by default bind: "lan", // CRITICAL: Only add your proxy's IP(s) here trustedProxies: ["10.0.0.1", "172.17.0.1"], auth: { mode: "trusted-proxy", trustedProxy: { // Header containing authenticated user identity (required) userHeader: "x-forwarded-user", // Optional: headers that MUST be present (proxy verification) requiredHeaders: ["x-forwarded-proto", "x-forwarded-host"], // Optional: restrict to specific users (empty = allow all) allowUsers: ["nick@example.com", "admin@company.org"], // Optional: allow a same-host loopback proxy after explicit opt-in allowLoopback: false, }, }, },}Référence de configuration
gateway.trustedProxiesstring[]requiredTableau d’adresses IP de proxy à approuver. Les requêtes provenant d’autres IP sont rejetées.
gateway.auth.modestringrequiredDoit être "trusted-proxy".
gateway.auth.trustedProxy.userHeaderstringrequiredNom de l’en-tête contenant l’identité de l’utilisateur authentifié.
gateway.auth.trustedProxy.requiredHeadersstring[]En-têtes supplémentaires qui doivent être présents pour que la requête soit considérée comme fiable.
gateway.auth.trustedProxy.allowUsersstring[]Liste d’autorisation des identités utilisateur. Vide signifie autoriser tous les utilisateurs authentifiés.
gateway.auth.trustedProxy.allowLoopbackbooleanPrise en charge opt-in des proxys inverses loopback sur le même hôte. Par défaut : false.
Terminaison TLS et HSTS
Utilisez un seul point de terminaison TLS et appliquez HSTS à cet endroit.
Terminaison TLS du proxy (recommandé)
Lorsque votre proxy inverse gère HTTPS pour https://control.example.com, définissez Strict-Transport-Security au niveau du proxy pour ce domaine.
- Bon choix pour les déploiements exposés à Internet.
- Conserve le certificat et la politique de renforcement HTTP au même endroit.
- OpenClaw peut rester en HTTP loopback derrière le proxy.
Exemple de valeur d’en-tête :
Strict-Transport-Security: max-age=31536000; includeSubDomainsTerminaison TLS du Gateway
Si OpenClaw sert lui-même HTTPS directement (sans proxy de terminaison TLS), définissez :
{ gateway: { tls: { enabled: true }, http: { securityHeaders: { strictTransportSecurity: "max-age=31536000; includeSubDomains", }, }, },}strictTransportSecurity accepte une valeur d’en-tête sous forme de chaîne, ou false pour désactiver explicitement.
Conseils de déploiement
- Commencez d’abord avec une durée maximale courte (par exemple
max-age=300) pendant que vous validez le trafic. - Augmentez vers des valeurs longue durée (par exemple
max-age=31536000) uniquement lorsque la confiance est élevée. - Ajoutez
includeSubDomainsuniquement si chaque sous-domaine est prêt pour HTTPS. - Utilisez le préchargement uniquement si vous respectez intentionnellement les exigences de préchargement pour l’ensemble complet de vos domaines.
- Le développement local limité au loopback ne bénéficie pas de HSTS.
Exemples de configuration de proxy
Pomerium
Pomerium transmet l’identité dans x-pomerium-claim-email (ou d’autres en-têtes de revendication) et un JWT dans x-pomerium-jwt-assertion.
{ gateway: { bind: "lan", trustedProxies: ["10.0.0.1"], // Pomerium's IP auth: { mode: "trusted-proxy", trustedProxy: { userHeader: "x-pomerium-claim-email", requiredHeaders: ["x-pomerium-jwt-assertion"], }, }, },}Extrait de configuration Pomerium :
routes: - from: https://openclaw.example.com to: http://openclaw-gateway:18789 policy: - allow: or: - email: is: nick@example.com pass_identity_headers: trueCaddy avec OAuth
Caddy avec le plugin caddy-security peut authentifier les utilisateurs et transmettre des en-têtes d’identité.
{ gateway: { bind: "lan", trustedProxies: ["10.0.0.1"], // Caddy/sidecar proxy IP auth: { mode: "trusted-proxy", trustedProxy: { userHeader: "x-forwarded-user", }, }, },}Extrait Caddyfile :
openclaw.example.com { authenticate with oauth2_provider authorize with policy1 reverse_proxy openclaw:18789 { header_up X-Forwarded-User {http.auth.user.email} }}nginx + oauth2-proxy
oauth2-proxy authentifie les utilisateurs et transmet l’identité dans x-auth-request-email.
{ gateway: { bind: "lan", trustedProxies: ["10.0.0.1"], // nginx/oauth2-proxy IP auth: { mode: "trusted-proxy", trustedProxy: { userHeader: "x-auth-request-email", }, }, },}Extrait de configuration nginx :
location / { auth_request /oauth2/auth; auth_request_set $user $upstream_http_x_auth_request_email; proxy_pass http://openclaw:18789; proxy_set_header X-Auth-Request-Email $user; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";}Traefik avec authentification transférée
{ gateway: { bind: "lan", trustedProxies: ["172.17.0.1"], // Traefik container IP auth: { mode: "trusted-proxy", trustedProxy: { userHeader: "x-forwarded-user", }, }, },}Configuration mixte de jeton
OpenClaw rejette les configurations ambiguës où un gateway.auth.token (ou OPENCLAW_GATEWAY_TOKEN) et le mode trusted-proxy sont actifs en même temps. Les configurations mixtes de jeton peuvent provoquer l’authentification silencieuse des requêtes loopback sur le mauvais chemin d’authentification.
Si vous voyez une erreur mixed_trusted_proxy_token au démarrage :
- Supprimez le jeton partagé lorsque vous utilisez le mode trusted-proxy, ou
- Basculez
gateway.auth.modevers"token"si vous souhaitez une authentification basée sur jeton.
Les en-têtes d’identité de proxy de confiance local loopback continuent d’échouer de manière fermée : les appelants du même hôte ne sont pas authentifiés silencieusement comme utilisateurs du proxy. Les appelants OpenClaw internes qui contournent le proxy peuvent s’authentifier avec gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD à la place. Le repli sur jeton reste volontairement non pris en charge en mode proxy de confiance.
En-tête des portées opérateur
L’authentification par proxy de confiance est un mode HTTP porteur d’identité ; les appelants peuvent donc déclarer facultativement des portées opérateur avec x-openclaw-scopes sur les requêtes d’API HTTP.
Remarque : les portées WebSocket sont déterminées par la négociation du protocole Gateway et la liaison d’identité de l’appareil. Sur les requêtes de mise à niveau WebSocket de la Control UI, x-openclaw-scopes ne fait que plafonner les portées de session négociées ; ce n’est pas une attribution. Pour le comportement des portées WebSocket avec un proxy de confiance, consultez Comportement d’appairage de la Control UI.
Exemples :
x-openclaw-scopes: operator.readx-openclaw-scopes: operator.read,operator.writex-openclaw-scopes: operator.admin,operator.write
Comportement :
- Lorsque l’en-tête est présent, OpenClaw respecte l’ensemble de portées déclaré.
- Lorsque l’en-tête est présent mais vide, la requête ne déclare aucune portée opérateur.
- Lorsque l’en-tête est absent, les API HTTP normales porteuses d’identité se replient sur l’ensemble standard de portées opérateur par défaut.
- Les routes HTTP de Plugin avec authentification Gateway sont plus restreintes par défaut : lorsque
x-openclaw-scopesest absent, leur portée d’exécution se replie suroperator.write. - Les requêtes HTTP d’origine navigateur doivent toujours passer
gateway.controlUi.allowedOrigins(ou le mode de repli délibéré sur l’en-tête Host), même après la réussite de l’authentification par proxy de confiance. - Pour les sessions WebSocket de la Control UI,
x-openclaw-scopesplafonne les portées lorsqu’il est présent sur la requête de mise à niveau. Une valeur vide ne produit aucune portée.
Règle pratique : envoyez x-openclaw-scopes explicitement lorsque vous voulez qu’une requête par proxy de confiance soit plus restreinte que les valeurs par défaut, ou lorsqu’une route de Plugin avec authentification Gateway a besoin de quelque chose de plus fort que la portée d’écriture.
Liste de contrôle de sécurité
Avant d’activer l’authentification par proxy de confiance, vérifiez :
- [ ] Le proxy est le seul chemin : le port Gateway est protégé par pare-feu contre tout sauf votre proxy.
- [ ] trustedProxies est minimal : uniquement les IP réelles de votre proxy, pas des sous-réseaux entiers.
- [ ] La source de proxy loopback est délibérée : l’authentification par proxy de confiance échoue de manière fermée pour les requêtes provenant d’une source loopback, sauf si
gateway.auth.trustedProxy.allowLoopbackest explicitement activé pour un proxy sur le même hôte. - [ ] Le proxy supprime les en-têtes : votre proxy remplace (et n’ajoute pas à) les en-têtes
x-forwarded-*des clients. - [ ] Terminaison TLS : votre proxy gère TLS ; les utilisateurs se connectent via HTTPS.
- [ ] allowedOrigins est explicite : une Control UI non loopback utilise
gateway.controlUi.allowedOriginsexplicite. - [ ] allowUsers est défini (recommandé) : restreignez aux utilisateurs connus plutôt que d’autoriser toute personne authentifiée.
- [ ] Aucune configuration mixte de jeton : ne définissez pas à la fois
gateway.auth.tokenetgateway.auth.mode: "trusted-proxy". - [ ] Le repli sur mot de passe local est privé : si vous configurez
gateway.auth.passwordpour des appelants directs internes, gardez le port Gateway derrière un pare-feu afin que les clients distants hors proxy ne puissent pas l’atteindre directement.
Audit de sécurité
openclaw security audit signalera l’authentification par proxy de confiance avec une sévérité critique. C’est intentionnel : c’est un rappel que vous déléguez la sécurité à votre configuration de proxy.
L’audit vérifie :
- Rappel/avertissement critique de base
gateway.trusted_proxy_auth - Configuration
trustedProxiesmanquante - Configuration
userHeadermanquante allowUsersvide (autorise tout utilisateur authentifié)allowLoopbackactivé pour des sources proxy sur le même hôte- Politique d’origine navigateur générique ou manquante sur les surfaces exposées de la Control UI
Dépannage
trusted_proxy_untrusted_source
La requête ne provenait pas d’une IP dans gateway.trustedProxies. Vérifiez :
- L’IP du proxy est-elle correcte ? (Les IP de conteneurs Docker peuvent changer.)
- Y a-t-il un équilibreur de charge devant votre proxy ?
- Utilisez
docker inspectoukubectl get pods -o widepour trouver les IP réelles.
trusted_proxy_loopback_source
OpenClaw a rejeté une requête de proxy de confiance provenant d’une source loopback.
Vérifiez :
- Le proxy se connecte-t-il depuis
127.0.0.1/::1? - Essayez-vous d’utiliser l’authentification par proxy de confiance avec un proxy inverse loopback sur le même hôte ?
Correctif :
- Préférez l’authentification par jeton/mot de passe pour les clients internes sur le même hôte qui ne passent pas par le proxy, ou
- Acheminez via une adresse de proxy de confiance non loopback et conservez cette IP dans
gateway.trustedProxies, ou - Pour un proxy inverse délibéré sur le même hôte, définissez
gateway.auth.trustedProxy.allowLoopback = true, conservez l’adresse loopback dansgateway.trustedProxieset assurez-vous que le proxy supprime ou remplace les en-têtes d’identité.
trusted_proxy_user_missing
L’en-tête utilisateur était vide ou manquant. Vérifiez :
- Votre proxy est-il configuré pour transmettre les en-têtes d’identité ?
- Le nom de l’en-tête est-il correct ? (insensible à la casse, mais l’orthographe compte)
- L’utilisateur est-il réellement authentifié au niveau du proxy ?
trusted_proxy_missing_header_*
Un en-tête requis était absent. Vérifiez :
- Votre configuration de proxy pour ces en-têtes spécifiques.
- Si les en-têtes sont supprimés quelque part dans la chaîne.
trusted_proxy_user_not_allowed
L’utilisateur est authentifié mais n’est pas dans allowUsers. Ajoutez-le ou supprimez la liste d’autorisation.
trusted_proxy_origin_not_allowed
L’authentification par proxy de confiance a réussi, mais l’en-tête navigateur Origin n’a pas passé les contrôles d’origine de la Control UI.
Vérifiez :
gateway.controlUi.allowedOriginsinclut l’origine navigateur exacte.- Vous ne vous appuyez pas sur des origines génériques, sauf si vous voulez intentionnellement un comportement qui autorise tout.
- Si vous utilisez intentionnellement le mode de repli sur l’en-tête Host,
gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=trueest défini délibérément.
La connexion réussit mais les méthodes signalent une portée manquante
Le WebSocket se connecte, mais chat.history, sessions.list ou
models.list échoue avec missing scope: operator.read.
Causes courantes :
- Session Control UI sans appareil : l’authentification par proxy de confiance peut admettre la connexion WebSocket sans identité d’appareil, mais OpenClaw efface les portées des sessions sans appareil par conception.
- Client backend personnalisé :
gateway.controlUi.dangerouslyDisableDeviceAuthest limité à la Control UI et n’accorde pas de portées à des clients WebSocket arbitraires de type backend ou CLI. x-openclaw-scopestrop restreint : si votre proxy injecte cet en-tête sur la requête de mise à niveau WebSocket de la Control UI, les portées de session sont plafonnées à cet ensemble. Une valeur d’en-tête vide ne produit aucune portée.
Correctif :
- Pour la Control UI, utilisez HTTPS afin que le navigateur puisse générer l’identité d’appareil et terminer l’appairage.
- Pour une automatisation personnalisée, utilisez l’identité/l’appairage d’appareil, le chemin d’assistance backend direct-local réservé
gateway-client, ou RPC HTTP d’administration. - Utilisez
gateway.controlUi.dangerouslyDisableDeviceAuth: trueuniquement comme chemin temporaire de secours de la Control UI.
WebSocket échoue toujours
Assurez-vous que votre proxy :
- Prend en charge les mises à niveau WebSocket (
Upgrade: websocket,Connection: upgrade). - Transmet les en-têtes d’identité sur les requêtes de mise à niveau WebSocket (pas seulement HTTP).
- N’a pas de chemin d’authentification séparé pour les connexions WebSocket.
Migration depuis l’authentification par jeton
Si vous passez de l’authentification par jeton au proxy de confiance :
Configurer le proxy
Configurez votre proxy pour authentifier les utilisateurs et transmettre les en-têtes.
Tester le proxy indépendamment
Testez la configuration du proxy indépendamment (curl avec en-têtes).
Mettre à jour la configuration OpenClaw
Mettez à jour la configuration OpenClaw avec l’authentification par proxy de confiance.
Redémarrer le Gateway
Redémarrez le Gateway.
Tester WebSocket
Testez les connexions WebSocket depuis la Control UI.
Auditer
Exécutez openclaw security audit et examinez les résultats.
Connexe
- Configuration — référence de configuration
- Accès distant — autres modèles d’accès distant
- Sécurité — guide de sécurité complet
- Tailscale — alternative plus simple pour un accès limité au tailnet