Mettre une application derrière un SSO avec oauth2-proxy
Protégez une application sans login avec OIDC et oauth2-proxy. Configurez forward auth avec nginx ou Traefik et évitez les pièges de cookies et de redirection.
Authentification déportée : comment fournir un SSO à une application sans connexion
oauth2-proxy fournit un single sign-on à une application qui n’a pas de système de connexion propre. Cela fonctionne parce que le reverse proxy placé devant l’application intercepte chaque requête, demande à oauth2-proxy si la requête contient une session valide, puis ne transmet la requête à l’upstream que si la réponse est positive. Le code de l’application ne change jamais, car l’application ne voit jamais ce contrôle.
Le contrôle ajoute une requête HTTP. Le proxy envoie une copie des en-têtes de la requête entrante à /oauth2/auth et lit le code d’état. Un code 202 signifie que l’appelant possède une session ; le proxy transmet donc la requête d’origine à l’application. Un code 401 signifie qu’aucune session n’est présente ; le proxy redirige alors le navigateur vers /oauth2/sign_in, qui démarre une connexion OpenID Connect (OIDC) auprès de votre fournisseur d’identité. OIDC est la couche d’identité construite au-dessus d’OAuth 2.0, et le fournisseur est celui que vous utilisez déjà pour les connexions.
Ce modèle possède un nom dans chaque reverse proxy. Nginx appelle la directive auth_request. Traefik appelle le middleware forwardAuth. Caddy l’écrit forward_auth. Le service qui répond à la sous-requête peut également être remplacé. oauth2-proxy est le choix courant, car il parle directement OIDC et n’a pas besoin de sa propre base de données.
Définissez la limite de confiance avant d’écrire la moindre configuration
Après une vérification réussie, oauth2-proxy renvoie l’identité dans des en-têtes de réponse, puis le reverse proxy les recopie dans la requête envoyée à l’upstream. Avec set_xauthrequest activé, vous obtenez X-Auth-Request-User et X-Auth-Request-Email. L’application lit ces en-têtes et leur fait confiance.
C’est tout le modèle de sécurité. Il faut donc en expliciter la conséquence. Tout ce qui peut ouvrir une connexion TCP vers le port de l’application peut définir lui-même ces en-têtes et se faire passer pour n’importe quel utilisateur. Un seul curl -H "X-Auth-Request-Email: admin@example.com" http://app-host:3000/ suffit à contourner complètement la protection s’il atteint directement l’application.
L’application ne doit donc être accessible qu’à travers le proxy. Dans Docker Compose, supprimez le mapping ports: du service applicatif et laissez celui-ci sur le réseau interne, afin que seul le conteneur du proxy puisse s’y connecter. Sur un hôte classique, liez l’application à 127.0.0.1:3000 au lieu de 0.0.0.0:3000. Vérifiez ensuite ce qui est réellement exposé :
sudo ss -tlnp | grep 3000Une ligne contenant 0.0.0.0:3000 signifie que l’application répond sur l’adresse IP publique et que votre contrôle d’accès est purement décoratif. 127.0.0.1:3000 est le résultat attendu. Une règle de pare-feu constitue une deuxième couche utile, mais l’adresse d’écoute reste en place même si un autre outil vide votre jeu de règles.
Installer oauth2-proxy
En août 2026, la version actuelle est v7.15.3, publiée en juin 2026. Installez le binaire et vérifiez le téléchargement :
cd /tmp
curl -fsSLO https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.15.3/oauth2-proxy-v7.15.3.linux-amd64.tar.gz
curl -fsSLO https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.15.3/oauth2-proxy-v7.15.3.linux-amd64.tar.gz-sha256sum.txt
sha256sum -c oauth2-proxy-v7.15.3.linux-amd64.tar.gz-sha256sum.txt
tar -xzf oauth2-proxy-v7.15.3.linux-amd64.tar.gz
sudo install -m 755 oauth2-proxy-v7.15.3.linux-amd64/oauth2-proxy /usr/local/bin/oauth2-proxy
oauth2-proxy --versionsha256sum -c doit afficher une ligne se terminant par OK. S’il affiche FAILED, arrêtez-vous et téléchargez de nouveau le fichier au lieu d’exécuter le binaire.
Avec Docker, l’image est quay.io/oauth2-proxy/oauth2-proxy et vous devez épingler le tag : quay.io/oauth2-proxy/oauth2-proxy:v7.15.3. Le laisser sur latest transforme une simple docker compose pull en mise à niveau imprévue du processus qui protège toutes les applications du serveur.
Générer le secret du cookie
Le cookie de session est chiffré et cookie_secret en est la clé. Il doit contenir exactement 16, 24 ou 32 octets, car il devient une clé AES (Advanced Encryption Standard). Avec toute autre longueur, oauth2-proxy refuse de démarrer et affiche une erreur de démarrage qui mentionne le secret du cookie.
openssl rand -base64 32 | tr -- '+/' '-_'Le tr n’est pas cosmétique. Il convertit le base64 standard en alphabet compatible avec les URL. La valeur peut ainsi être utilisée dans un shell, un fichier env et un en-tête HTTP sans problème de guillemets.
Deux règles s’appliquent à cette valeur. Utilisez un secret différent pour chaque déploiement. Si vous exécutez plusieurs instances oauth2-proxy derrière le même domaine, utilisez le même secret pour toutes. Un cookie chiffré par une instance doit en effet pouvoir être déchiffré par les autres.
Rédiger la configuration d’oauth2-proxy
Conservez les paramètres dans un fichier plutôt que dans une longue ligne de commande, afin que le secret client n’apparaisse jamais dans la sortie de ps.
# /etc/oauth2-proxy/oauth2-proxy.cfg
http_address = "127.0.0.1:4180"
reverse_proxy = true
provider = "oidc"
oidc_issuer_url = "https://id.example.com/application/o/myapp/"
client_id = "REPLACE_ME"
client_secret = "REPLACE_ME"
redirect_url = "https://app.example.com/oauth2/callback"
cookie_secret = "REPLACE_ME"
cookie_secure = true
cookie_domains = [".example.com"]
whitelist_domains = [".example.com"]
email_domains = ["*"]
set_xauthrequest = true
upstreams = ["static://202"]reverse_proxy = true indique à oauth2-proxy de faire confiance aux en-têtes X-Forwarded-* envoyés par le proxy placé devant lui. Sans ce paramètre, oauth2-proxy considère l’adresse du proxy comme celle du client et peut déterminer incorrectement si la requête est arrivée via HTTPS.
upstreams = ["static://202"] fait répondre oauth2-proxy avec le code 202 lorsqu’une requête est authentifiée, sans rien proxyfier. C’est exactement ce qu’il faut pour l’authentification déléguée, puisque le reverse proxy se charge du proxying. Dans l’autre modèle de déploiement, oauth2-proxy se trouve directement dans le chemin des requêtes, avec upstreams = ["http://127.0.0.1:3000"] et sans aucun auth_request. Cette approche est plus simple pour une seule application, mais elle ne passe pas à l’échelle pour dix applications.
email_domains = ["*"] autorise toutes les adresses que votre fournisseur authentifie. Limitez-le à votre propre domaine ou, mieux, restreignez l’accès avec une association de groupe dans le fournisseur, puisque c’est là que vous gérez déjà les utilisateurs.
Exécutez-le sous systemd avec son propre utilisateur :
# /etc/systemd/system/oauth2-proxy.service
[Unit]
Description=oauth2-proxy
After=network-online.target
Wants=network-online.target
[Service]
User=oauth2-proxy
Group=oauth2-proxy
ExecStart=/usr/local/bin/oauth2-proxy --config=/etc/oauth2-proxy/oauth2-proxy.cfg
Restart=on-failure
ProtectSystem=strict
PrivateTmp=true
NoNewPrivileges=true
[Install]
WantedBy=multi-user.targetsudo useradd --system --no-create-home --shell /usr/sbin/nologin oauth2-proxy
sudo install -d -m 750 /etc/oauth2-proxy
sudo chown -R oauth2-proxy:oauth2-proxy /etc/oauth2-proxy
sudo chmod 600 /etc/oauth2-proxy/oauth2-proxy.cfg
sudo systemctl daemon-reload
sudo systemctl enable --now oauth2-proxy
curl -s http://127.0.0.1:4180/pingL’affichage de /ping et de OK indique que le processus a démarré et chargé sa configuration. Il s’agit du propre endpoint de santé d’oauth2-proxy, qui ne demande jamais de session. Si aucune réponse n’est reçue, consultez journalctl -u oauth2-proxy -n 50 : une URL d’issuer incorrecte et un secret de cookie d’une longueur invalide provoquent tous deux un échec au démarrage, et le journal l’indique dans les deux cas.
Enregistrez l’URI de redirection auprès de votre fournisseur
Créez une application OIDC chez votre fournisseur et définissez son URI de redirection sur la valeur exacte de redirect_url dans la configuration : https://app.example.com/oauth2/callback. Exacte signifie que le schéma, l’hôte, le port et le chemin correspondent caractère par caractère. Un slash final produit une URI différente.
C’est l’échec le plus fréquent de toute la configuration. Il se produit avant même l’intervention d’oauth2-proxy. Le fournisseur rejette la demande d’autorisation et affiche sa propre page d’erreur. Rien n’apparaît donc dans le journal d’oauth2-proxy. L’indice se trouve dans la barre d’adresse : le navigateur est toujours sur le domaine de votre fournisseur, et la chaîne de requête contient error=invalid_request ou la page nomme directement redirect_uri. Dans ce cas, corrigez l’enregistrement de l’application chez le fournisseur, pas la configuration du proxy.
Copiez l’URL de l’issuer depuis le fournisseur au lieu de la saisir manuellement. oauth2-proxy ajoute /.well-known/openid-configuration à oidc_issuer_url et récupère ce document de découverte au démarrage. Vérifiez-le d’abord vous-même :
curl -s https://id.example.com/application/o/myapp/.well-known/openid-configuration | head -c 400Un document JSON contenant une clé authorization_endpoint signifie que l’URL de l’issuer est correcte. Une erreur 404 ou une page d’erreur HTML signifie qu’elle est incorrecte. oauth2-proxy échouera alors au démarrage avec cette même erreur 404. Si vous n’avez pas encore choisi de fournisseur, la comparaison de Keycloak, Authentik et Zitadel présente les compromis, et exécuter Authentik comme votre propre serveur SSO décrit la partie fournisseur de cette configuration exacte.
Nginx : auth_request
Nginx gère l’authentification déléguée avec auth_request, qui lance une sous-requête interne et prend une décision selon son code d’état.
# in the http context, next to your other maps
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name app.example.com;
location /oauth2/ {
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Auth-Request-Redirect $request_uri;
}
location = /oauth2/auth {
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header Content-Length "";
proxy_pass_request_body off;
}
location / {
auth_request /oauth2/auth;
error_page 401 = @oauth2_signin;
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location @oauth2_signin {
return 302 /oauth2/sign_in?rd=$scheme://$host$request_uri;
}
}Trois détails justifient leur présence. proxy_pass_request_body off avec un Content-Length vide empêche nginx de copier le corps de chaque requête POST dans la sous-requête. C’est important, car oauth2-proxy ne lit pas ce corps. Lors d’un upload de fichier, la configuration par défaut envoie le fichier deux fois.
L’ensemble auth_request_set $auth_cookie et add_header Set-Cookie transmet au navigateur un cookie de session renouvelé. Si vous l’omettez, cookie_refresh ne fait discrètement rien, car nginx ignore le Set-Cookie de la sous-requête et le navigateur conserve l’ancienne valeur jusqu’à l’expiration de la session.
error_page 401 = @oauth2_signin transforme un contrôle échoué en redirection vers la connexion. Sans cette directive, un visiteur non authentifié obtient une simple page 401 Authorization Required, sans possibilité de poursuivre.
Testez toujours la configuration avant de recharger nginx :
sudo nginx -t && sudo systemctl reload nginxSi les directives utilisées autour de cette configuration ne vous sont pas familières, l’anatomie d’une configuration de reverse proxy nginx présente la couche sous-jacente.
Traefik : middleware forwardAuth
Traefik a besoin de deux middlewares pour cette fonction. Le premier effectue le contrôle. Le second transforme la réponse 401 en redirection du navigateur.
# dynamic configuration
http:
middlewares:
oauth-auth:
forwardAuth:
address: https://oauth.example.com/oauth2/auth
trustForwardHeader: true
oauth-errors:
errors:
status:
- "401-403"
service: oauth-backend
query: "/oauth2/sign_in?rd={url}"
statusRewrites:
"401": 302Associez les deux au router qui expose votre application, puis publiez oauth2-proxy sur son propre router à oauth.example.com, car le navigateur doit pouvoir atteindre /oauth2/sign_in et /oauth2/callback sans passer par le contrôle.
statusRewrites, qui transforme 401 en 302, est le point souvent oublié. Sans cette configuration, Traefik renvoie la redirection vers la page de connexion avec un statut 401. Le navigateur ne la suit pas et le visiteur voit une page contenant uniquement le mot Found.
trustForwardHeader: true transmet l’hôte et l’URI d’origine à oauth2-proxy. Celui-ci en a besoin pour construire la valeur rd, qui renvoie l’utilisateur vers la page demandée. Définissez whitelist_domains pour couvrir également cet hôte. Sinon, oauth2-proxy supprime le paramètre rd, car il le considère comme un risque d’open redirect, et tout le monde arrive sur / après la connexion. Un serveur Traefik expose généralement plusieurs applications à la fois. L’article faire passer plusieurs applications Docker Compose par une seule instance Traefik présente la disposition des routers utilisée ici.
Caddy: forward_auth
app.example.com {
handle /oauth2/* {
reverse_proxy oauth2-proxy.internal:4180 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Uri {uri}
}
}
handle {
forward_auth oauth2-proxy.internal:4180 {
uri /oauth2/auth
header_up X-Real-IP {remote_host}
copy_headers X-Auth-Request-User X-Auth-Request-Email
@error status 401
handle_response @error {
redir * /oauth2/sign_in?rd={scheme}://{host}{uri}
}
}
reverse_proxy upstream.internal:3000
}
}L’ordre est important ici. Le bloc /oauth2/* vient en premier et ne contient aucun forward_auth, car un visiteur qui n’est pas connecté doit pouvoir atteindre les chemins de connexion et de callback. Placez le contrôle avant ces chemins : les redirections de connexion renvoient alors vers elles-mêmes jusqu’à ce que le navigateur abandonne.
copy_headers transmet l’identité à la requête destinée à l’upstream, et ne produit des valeurs que lorsqu’oauth2-proxy s’exécute avec set_xauthrequest = true. Le choix entre les proxies est une question distincte ; la comparaison de nginx, Caddy et Traefik l’examine.
Pourquoi la connexion revient-elle à la page de connexion ?
Vous vous authentifiez auprès du fournisseur, qui vous redirige vers votre site, puis oauth2-proxy vous renvoie immédiatement vers le fournisseur. Cette boucle signifie que la requête de callback est arrivée sans le cookie défini par oauth2-proxy avant la redirection. Son journal indique le cas rencontré :
No cookies were found in OAuth callback.ou, lorsqu’un autre cookie est bien arrivé mais pas le bon :
Cookies were found in OAuth callback, but none was a CSRF cookie.CSRF signifie falsification de requête intersite. Ce cookie permet d’associer le callback à la connexion qui l’a déclenché. Le navigateur affiche le même échec sous la forme suivante :
Login Failed: Unable to find a valid CSRF token. Please try again.Vérifiez ces quatre causes dans l’ordre.
cookie_secure = truealors que le navigateur a accédé au site en HTTP non chiffré. Un navigateur n’enregistre pas un cookie marquéSecuresur une originehttp://; il ne le renvoie donc jamais. Configurez correctement la terminaison TLS (transport layer security), ou définissezcookie_secure = falseuniquement pendant les tests sur localhost.- Une valeur
cookie_domainsqui ne couvre pas le hostname affiché dans la barre d’adresse..example.comcouvreapp.example.comet ne fait absolument rien pourapp.example.net. - Le navigateur supprime le cookie. Une extension de confidentialité stricte ou le blocage des cookies tiers peut supprimer
_oauth2_proxy_csrfentre la redirection sortante et le callback. - Un décalage d’horloge. Si l’horloge du serveur est très différente de celle du fournisseur, les valeurs
iatetexpdu jeton ID sortent de la fenêtre acceptée et la session est rejetée à son arrivée.timedatectldoit signalerSystem clock synchronized: yes.
Observez le problème depuis le serveur au lieu de procéder par déduction :
sudo journalctl -u oauth2-proxy -fOuvrez l’application dans une fenêtre privée. Chaque requête est journalisée avec son statut. Un callback immédiatement suivi d’une nouvelle redirection vers le fournisseur confirme la boucle.
Chemins qui doivent contourner la connexion : API, webhooks et websockets
L’authentification déléguée suppose qu’un navigateur possède un cookie. Les clients qui n’utilisent pas de navigateur échouent.
Un client d’API qui envoie Authorization: Bearer <token> ne possède pas de cookie. Il reçoit donc une réponse 302 vers la page de connexion de votre fournisseur, puis tente d’analyser du HTML comme du JSON. Deux solutions simples existent. Définir skip_jwt_bearer_tokens = true permet à oauth2-proxy d’accepter un bearer token JWT (JSON web token) valide provenant du même issuer. Cette option convient lorsque vos clients d’API obtiennent déjà leurs tokens auprès du fournisseur. Sinon, excluez le chemin :
skip_auth_routes = [
"^/api/",
"POST=^/webhook/",
"GET=^/healthz$"
]Chaque valeur est une expression régulière comparée au chemin normalisé. Elle peut être précédée d’une méthode HTTP et de =. POST=^/webhook/ laisse le récepteur du webhook accessible en POST, tandis qu’un utilisateur qui consulte le même chemin dans un navigateur est toujours redirigé vers la connexion. Chaque entrée crée une ouverture dans votre protection. Ancrez donc les expressions avec ^ et limitez-les autant que possible au périmètre requis par l’appelant.
Les websockets sont souvent mal configurés. La requête d’upgrade est une requête HTTP GET ordinaire qui contient les mêmes cookies que les autres requêtes. Elle passe donc normalement le contrôle et ne nécessite aucune exception. Le problème vient du proxy autour de cette requête. Sans les en-têtes Upgrade et Connection sur l’emplacement protégé, l’upgrade n’aboutit jamais et le client de l’application réessaie indéfiniment avec un message WebSocket connection ... failed dans la console du navigateur. Exclure le chemin ne résout rien, car la requête a déjà été autorisée.
Une limite réelle subsiste. Le contrôle s’exécute une seule fois, au moment de l’upgrade. Un websocket qui reste ouvert pendant des heures n’est jamais contrôlé à nouveau. La suppression d’un utilisateur chez votre fournisseur ne ferme donc pas le socket qu’il détient déjà. Redémarrez l’application pour couper les connexions actives.
Stockage de session et cookie trop volumineux
Par défaut, toute la session est stockée dans le cookie, chiffrée avec votre cookie_secret. oauth2-proxy reste ainsi stateless et ne nécessite aucun service supplémentaire. Cette approche a toutefois une limite : les navigateurs plafonnent la taille d’un cookie à environ 4 KB. Lorsque l’ID token contient une longue liste de group claims, oauth2-proxy répartit la session entre _oauth2_proxy_0, _oauth2_proxy_1, puis les cookies suivants. Au-delà de quelques parties, les en-têtes de la requête deviennent suffisamment volumineux pour que nginx renvoie 400 Request Header Or Cookie Too Large avant même que l’application ne reçoive la requête.
Dans ce cas, déplacez la session côté serveur :
session_store_type = "redis"
redis_connection_url = "redis://127.0.0.1:6379"Le navigateur ne conserve alors qu’un ticket court, tandis que la session chiffrée est stockée dans Redis. En contrepartie, Redis doit rester disponible : s’il tombe, toutes les sessions deviennent invalides et tous les utilisateurs sont déconnectés en même temps. Le cookie store a son propre inconvénient : deux requêtes qui actualisent la même session au même moment peuvent entrer en conflit et imposer une nouvelle authentification.
Ce que l’authentification forward auth ne vous apporte pas
Il s’agit d’un contrôle à l’entrée. Ce n’est pas une autorisation dans l’application, et cette différence détermine si cette approche convient à votre cas.
Une fois l’utilisateur autorisé à passer, l’application voit ce qu’elle voyait déjà. Si l’application possède ses propres rôles, forward auth ne les renseigne pas, sauf si l’application prend en charge l’authentification par en-tête et associe un en-tête à un compte. Grafana le permet avec ses paramètres auth.proxy. La plupart des applications auto-hébergées ne le permettent pas. Pour l’application, tous les utilisateurs qui franchissent le contrôle sont donc la même identité unique, qui est souvent un compte administrateur.
Cette solution ne protège pas non plus les propres API tokens de l’application. Un personal access token émis par l’application authentifie l’accès à l’application, et non à oauth2-proxy. Il cesse donc de fonctionner dès que le contrôle est placé devant l’application. Exemptez le chemin de l’API pour le rétablir, et ce token devient alors le seul élément qui protège ce chemin. Vous exécutez désormais deux systèmes d’authentification sur un même service, et le SSO n’en couvre qu’un seul.
La révocation constitue une troisième limite. La suppression d’un utilisateur chez votre fournisseur empêche les nouvelles connexions et le renouvellement du token effectué par cookie_refresh, mais un cookie de session existant reste valide jusqu’à son expiration. Par défaut, cookie_expire vaut 168 heures, soit une semaine d’accès pour une personne que vous venez de supprimer. Définissez cookie_refresh sur une durée courte, par exemple une heure, afin que la révocation intervienne dans cette fenêtre.
La trace d’audit s’arrête également au niveau du contrôle. oauth2-proxy journalise l’identité des utilisateurs qui passent et l’heure de leur passage. L’application journalise une session sans nom. Si vous devez déterminer qui a modifié un paramètre, l’identité transmise par en-tête dans l’application constitue le minimum. De véritables comptes individuels dans l’application restent la réponse la plus fiable.
Lorsque payer l’option SSO est la meilleure solution
L’authentification déléguée est le bon outil lorsqu’une application n’a aucun système de connexion ou utilise un mot de passe partagé, et que vous voulez disposer d’un emplacement unique pour ajouter et supprimer des utilisateurs. Sa mise en place prend un après-midi et ajoute un processus, mais elle fonctionne avec toute application qui utilise HTTP.
C’est le mauvais outil lorsque plusieurs personnes ont besoin de permissions différentes dans une même application. Une passerelle ne peut pas exprimer « Ana peut modifier les tableaux de bord et Bo peut seulement les consulter ». Si l’éditeur vend une offre SSO, la correspondance entre groupes et rôles est généralement ce que vous achetez réellement. La reconstruire avec des en-têtes et des règles de proxy est plus fragile que de la payer. Le modèle tarifaire derrière ces offres SSO mérite d’être consulté avant de prendre une décision.
Deux autres situations vont dans le même sens. Les procédures de conformité qui exigent des traces d’audit par utilisateur dans l’application n’accepteront pas les journaux d’accès du proxy comme preuve. De plus, toute application disposant d’un client mobile ou de bureau qui ne transmet pas les cookies du navigateur rencontrera la passerelle à chaque requête.
FAQ
Qu’est-ce que l’authentification forward auth ?
L’authentification forward auth est un mécanisme dans lequel le reverse proxy interroge un service d’authentification distinct pour chaque requête entrante avant de la transmettre au backend. Le proxy envoie les en-têtes de la requête à un endpoint tel que /oauth2/auth et lit le code d’état. 202 signifie que la requête est autorisée : la requête d’origine est donc transmise à l’application. 401 signifie qu’aucune session n’est présente : le proxy redirige donc le navigateur vers une page de connexion. Nginx l’implémente avec la directive auth_request, Traefik avec le middleware forwardAuth et Caddy avec forward_auth.
Pourquoi oauth2-proxy me redirige-t-il vers la page de connexion en boucle ?
La requête de callback est arrivée jusqu’à oauth2-proxy sans son cookie CSRF. oauth2-proxy recommence donc le processus. Le journal du serveur contient No cookies were found in OAuth callback. et le navigateur affiche Login Failed: Unable to find a valid CSRF token. Please try again.. La cause habituelle est cookie_secure = true sur un site auquel le navigateur a accédé en HTTP non chiffré, car un navigateur n’enregistre pas de cookie Secure sur une origine http://. L’autre cause fréquente est une valeur cookie_domains qui ne couvre pas le nom d’hôte affiché dans la barre d’adresse.
Comment autoriser un client API ou un webhook à passer par oauth2-proxy ?
Utilisez skip_auth_routes avec une expression régulière ancrée, éventuellement limitée à une seule méthode HTTP, par exemple POST=^/webhook/. Si vos clients API possèdent déjà des JWT émis par le même fournisseur, skip_jwt_bearer_tokens = true accepte ces jetons à la place d’un cookie tout en conservant la protection du chemin. Tout ce qui figure dans skip_auth_routes est accessible sans authentification pour tout le monde. Gardez donc chaque expression aussi restrictive que le permet l’appelant.
oauth2-proxy fournit-il des permissions propres à chaque utilisateur à l’application ?
Non. Il sert de point de contrôle, pas de système d’autorisation. Il décide qui peut atteindre l’application. Tous les utilisateurs qui l’atteignent sont identiques pour l’application, sauf si celle-ci lit les en-têtes d’identité et les associe à des comptes. Grafana peut le faire avec ses paramètres auth.proxy. La plupart des applications auto-hébergées ne le peuvent pas. Toutes les personnes qui franchissent le point de contrôle utilisent donc la même identité que celle avec laquelle l’application s’exécute.
Quelqu’un peut-il contourner oauth2-proxy en définissant lui-même l’en-tête d’identité ?
Oui, s’il peut atteindre directement l’application. L’identité est transmise dans un en-tête en clair tel que X-Auth-Request-Email, et l’application fait confiance à la valeur reçue. Toute personne capable d’ouvrir une connexion vers le port de l’application peut envoyer cet en-tête et se faire passer pour n’importe quel utilisateur. Liez l’application à 127.0.0.1, ou laissez-la sur un réseau Docker interne sans port publié, puis vérifiez ce point avec sudo ss -tlnp.