SSD Nodes Learn 🎉 VPS da $5.50/mese
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-21

SSO per qualsiasi app con oauth2-proxy e OIDC

Scopri come proteggere un'app senza login con oauth2-proxy: configura forward auth in Nginx o Traefik ed evita errori di cookie e redirect.

Autenticazione forward: come fornire SSO a un'applicazione senza login

oauth2-proxy fornisce il single sign-on a un'applicazione che non dispone di un proprio sistema di accesso. Funziona perché il reverse proxy davanti all'applicazione blocca ogni richiesta, chiede a oauth2-proxy se la richiesta contiene una sessione valida e inoltra la richiesta al servizio upstream solo quando la risposta è positiva. Non è necessario modificare il codice dell'applicazione, perché l'applicazione non vede mai il controllo.

Il controllo consiste in un'ulteriore richiesta HTTP. Il proxy invia una copia degli header della richiesta in ingresso a /oauth2/auth e legge il codice di stato. Un codice 202 indica che il chiamante dispone di una sessione, quindi il proxy inoltra la richiesta originale all'applicazione. Un codice 401 indica che non esiste una sessione, quindi il proxy reindirizza il browser a /oauth2/sign_in, che avvia un accesso OpenID Connect (OIDC) presso il provider di identità. OIDC è il livello di identità basato su OAuth 2.0; il provider è quello che usi già per gli accessi.

Questo modello ha un nome in ogni reverse proxy. Nginx chiama la direttiva auth_request. Traefik chiama il middleware forwardAuth. Caddy lo indica come forward_auth. Anche il servizio che risponde alla sotto-richiesta è intercambiabile. oauth2-proxy è la scelta comune perché parla direttamente OIDC e non richiede un proprio database.

Disegnate il confine di attendibilità prima di scrivere la configurazione

Dopo un controllo riuscito, oauth2-proxy restituisce l’identità negli header della risposta e il reverse proxy li copia nella richiesta inviata al servizio upstream. Con set_xauthrequest abilitato, si ottengono X-Auth-Request-User e X-Auth-Request-Email. L’applicazione legge questi header e si fida del loro contenuto.

Questo è l’intero modello di sicurezza. È quindi necessario esplicitarne la conseguenza: qualsiasi soggetto in grado di aprire una connessione TCP alla porta dell’applicazione può impostare autonomamente questi header e assumere l’identità di qualsiasi utente. Un singolo curl -H "X-Auth-Request-Email: admin@example.com" http://app-host:3000/ consente di eludere completamente il controllo se raggiunge direttamente l’applicazione.

L’applicazione deve quindi essere raggiungibile soltanto tramite il proxy. In Docker Compose, rimuovere il mapping ports: dal servizio dell’applicazione e lasciarlo sulla rete interna, in modo che soltanto il container del proxy possa connettersi. Su un host bare metal, associare l’applicazione a 127.0.0.1:3000 invece di 0.0.0.0:3000. Verificare quindi ciò che è effettivamente esposto:

sudo ss -tlnp | grep 3000

Una riga con 0.0.0.0:3000 indica che l’applicazione risponde sull’IP pubblico e che il controllo è soltanto apparente. 127.0.0.1:3000 è il risultato desiderato. Una regola del firewall costituisce un secondo livello utile, ma l’indirizzo di bind resta efficace anche se un altro strumento svuota il ruleset.

Installare oauth2-proxy

Ad agosto 2026 la release corrente è v7.15.3, pubblicata a giugno 2026. Installare il binario e verificare il download:

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 --version

sha256sum -c deve stampare una riga che termina con OK. Se stampa FAILED, interrompere la procedura e scaricare nuovamente il file invece di eseguire il binario.

In Docker l'immagine è quay.io/oauth2-proxy/oauth2-proxy e il tag deve essere fissato: quay.io/oauth2-proxy/oauth2-proxy:v7.15.3. Lasciarlo su latest trasforma un normale docker compose pull in un aggiornamento non pianificato dell'unico processo che protegge tutte le applicazioni presenti sul server.

Il cookie di sessione è crittografato e cookie_secret è la chiave. Deve avere esattamente 16, 24 o 32 byte, perché viene usata come chiave AES (advanced encryption standard). Con qualsiasi altra lunghezza, oauth2-proxy rifiuta di avviarsi e restituisce un errore di avvio che identifica il secret del cookie.

openssl rand -base64 32 | tr -- '+/' '-_'

tr non è un dettaglio estetico. Converte la codifica base64 standard nell'alfabeto sicuro per gli URL, quindi il valore può essere usato in una shell, in un file env e in un header HTTP senza problemi di quoting.

Per questo valore valgono due regole. Usate un secret diverso per ogni deployment. Se eseguite più istanze di oauth2-proxy dietro lo stesso dominio, assegnate a tutte lo stesso secret, perché un cookie crittografato da un'istanza deve poter essere letto dalle altre.

Scrivere la configurazione di oauth2-proxy

Conservare le impostazioni in un file invece di usare una riga di comando lunga, in modo che il client secret non compaia mai nell'output di 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 indica a oauth2-proxy di considerare attendibili gli header X-Forwarded-* provenienti dal proxy che lo precede. Senza questa impostazione, oauth2-proxy considera l'indirizzo del proxy come indirizzo del client e può determinare in modo errato se la richiesta è arrivata tramite HTTPS.

upstreams = ["static://202"] fa sì che oauth2-proxy risponda con 202 a una richiesta autenticata senza inoltrare nulla. È esattamente il comportamento richiesto da forward auth, perché a gestire il proxying è il reverse proxy. L'altra modalità di distribuzione inserisce direttamente oauth2-proxy nel percorso delle richieste con upstreams = ["http://127.0.0.1:3000"] e senza alcun auth_request. È più semplice per una sola applicazione, ma non è adatta a dieci applicazioni.

email_domains = ["*"] consente tutti gli indirizzi che il provider autentica. Limitare l'impostazione al proprio dominio oppure, meglio ancora, restringere l'accesso tramite un'associazione a un gruppo nel provider, perché è nel provider che gli utenti vengono già gestiti.

Eseguirlo tramite systemd con un utente dedicato:

# /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.target
sudo 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/ping

La stampa di /ping e OK indica che il processo è stato avviato e ha caricato la configurazione. È l'endpoint di health check interno di oauth2-proxy e non richiede mai una sessione. Se non riceve risposta, consultare journalctl -u oauth2-proxy -n 50, perché un issuer URL non valido e un cookie secret di lunghezza errata causano entrambi un errore all'avvio e lo indicano nei log.

Registrare l’URI di reindirizzamento presso il provider

Creare un’applicazione OIDC nel provider e impostare l’URI di reindirizzamento esattamente sul valore redirect_url della configurazione: https://app.example.com/oauth2/callback. Esattamente significa che schema, host, porta e percorso devono corrispondere carattere per carattere. Una barra finale rende l’URI diverso.

Questo è l’errore più comune dell’intera configurazione e si verifica prima ancora che intervenga oauth2-proxy. Il provider rifiuta la richiesta di autorizzazione e visualizza una propria pagina di errore, quindi nel log di oauth2-proxy non compare nulla. L’indizio è la barra degli indirizzi: il browser si trova ancora sul dominio del provider e la stringa di query contiene error=invalid_request oppure la pagina mostra direttamente redirect_uri. In questo caso, correggere il record dell’applicazione nel provider, non la configurazione del proxy.

Copiare l’URL dell’issuer dal provider invece di digitarlo. oauth2-proxy aggiunge /.well-known/openid-configuration a oidc_issuer_url e recupera quel documento di discovery all’avvio. Verificarlo prima manualmente:

curl -s https://id.example.com/application/o/myapp/.well-known/openid-configuration | head -c 400

Un JSON che contiene una chiave authorization_endpoint indica che l’URL dell’issuer è corretto. Un errore 404 o una pagina di errore HTML indicano che è errato; oauth2-proxy non riuscirà ad avviarsi per lo stesso errore 404. Se non è stato ancora scelto un provider, il confronto tra Keycloak, Authentik e Zitadel illustra i compromessi, mentre eseguire Authentik come server SSO personale descrive la parte relativa al provider di questa configurazione.

Nginx: auth_request

Nginx esegue l'autenticazione delegata con auth_request, che avvia una sotto-richiesta interna e agisce in base al relativo codice di stato.

# 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;
  }
}

Tre dettagli giustificano la loro presenza. proxy_pass_request_body off con un Content-Length vuoto impedisce a nginx di copiare il body di ogni POST nella sotto-richiesta. Questo è importante perché oauth2-proxy non lo legge. Durante il caricamento di un file, la configurazione predefinita invia il file due volte.

La coppia auth_request_set $auth_cookie e add_header Set-Cookie restituisce al browser il cookie di sessione aggiornato. Se la si omette, cookie_refresh non produce alcun effetto perché nginx scarta Set-Cookie della sotto-richiesta e il browser conserva il valore precedente fino alla scadenza della sessione.

error_page 401 = @oauth2_signin trasforma un controllo fallito in un reindirizzamento alla pagina di login. Senza questa direttiva, un visitatore non autenticato riceve una semplice pagina 401 Authorization Required e non ha modo di procedere.

Esegui sempre un test prima di ricaricare la configurazione:

sudo nginx -t && sudo systemctl reload nginx

Se le direttive circostanti non ti sono familiari, l'anatomia di una configurazione reverse proxy nginx descrive il livello sottostante.

Traefik: middleware forwardAuth

Per questa funzione, Traefik richiede due middleware. Il primo esegue il controllo. Il secondo converte il codice 401 in un redirect del browser.

# 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": 302

Collega entrambi al router che espone la tua applicazione e pubblica oauth2-proxy su un router separato all'indirizzo oauth.example.com, perché il browser deve poter raggiungere /oauth2/sign_in e /oauth2/callback senza passare dal controllo.

statusRewrites, che converte 401 in 302, è il passaggio che viene spesso omesso. Senza questa configurazione, Traefik restituisce il redirect di accesso con stato 401, il browser non lo segue e il visitatore visualizza una pagina contenente la sola parola Found.

trustForwardHeader: true inoltra l'host e l'URI originali a oauth2-proxy, che ne ha bisogno per creare il valore rd, usato per riportare l'utente alla pagina richiesta. Imposta whitelist_domains in modo da includere anche quell'host; in caso contrario oauth2-proxy elimina il parametro rd perché lo considera un rischio di open redirect e, dopo l'accesso, tutti gli utenti vengono portati a /. Un server Traefik espone spesso più applicazioni contemporaneamente; instradare più applicazioni Docker Compose tramite una singola istanza Traefik mostra la struttura dei router in cui si inserisce questa configurazione.

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’ordine è importante. Il blocco /oauth2/* viene prima e non contiene alcun forward_auth, perché un visitatore che non ha effettuato l’accesso deve poter raggiungere i percorsi di accesso e callback. Se si inserisce il controllo davanti a questi percorsi, il login esegue un redirect verso se stesso finché il browser interrompe il tentativo.

copy_headers trasferisce l’identità nella richiesta upstream e produce valori solo quando oauth2-proxy viene eseguito con set_xauthrequest = true. La scelta tra i proxy è una questione distinta; il confronto tra nginx, Caddy e Traefik la analizza.

Perché il login torna alla pagina di accesso?

Accedi presso il provider, il provider ti reindirizza al sito e oauth2-proxy ti invia subito di nuovo al provider. Il loop indica che la richiesta di callback è arrivata senza il cookie che oauth2-proxy aveva impostato prima del reindirizzamento. Il log identifica il caso:

No cookies were found in OAuth callback.

oppure, quando arriva un altro cookie ma non quello corretto:

Cookies were found in OAuth callback, but none was a CSRF cookie.

CSRF significa falsificazione di richieste cross-site. Questo cookie permette di associare la callback al login che l'ha avviata. Nel browser lo stesso problema appare come:

Login Failed: Unable to find a valid CSRF token. Please try again.

Controlla queste quattro cause, nell'ordine.

  1. cookie_secure = true mentre il browser ha raggiunto il sito tramite HTTP semplice. Un browser non memorizza un cookie contrassegnato come Secure su un'origine http://, quindi non lo invia mai al server. Configura correttamente la terminazione TLS (transport layer security) oppure imposta cookie_secure = false soltanto durante i test su localhost.
  2. Un valore cookie_domains che non comprende il nome host mostrato nella barra degli indirizzi. .example.com comprende app.example.com e non ha alcun effetto su app.example.net.
  3. Il browser elimina il cookie. Un'estensione con impostazioni di privacy restrittive o il blocco dei cookie di terze parti può rimuovere _oauth2_proxy_csrf tra il reindirizzamento in uscita e la callback.
  4. Deriva dell'orologio. Se l'orologio del server è molto diverso da quello del provider, iat e exp del token ID escono dalla finestra temporale accettata e la sessione viene rifiutata all'arrivo. timedatectl dovrebbe segnalare System clock synchronized: yes.

Osserva il problema dal lato server invece di procedere per ipotesi:

sudo journalctl -u oauth2-proxy -f

Apri l'applicazione in una finestra privata. Ogni richiesta viene registrata con il relativo stato, quindi una callback seguita immediatamente da un altro reindirizzamento al provider è il loop, come risulta dai log.

Percorsi che devono saltare il login: API, webhook e websocket

L’autenticazione forward presuppone un browser che dispone di un cookie. Le richieste provenienti da client senza browser non funzionano.

Un client API che invia Authorization: Bearer <token> non dispone di cookie, quindi riceve un 302 verso la pagina di login del provider e poi tenta di interpretare l’HTML come JSON. Esistono due soluzioni semplici. Impostando skip_jwt_bearer_tokens = true, oauth2-proxy accetta un token bearer JWT (JSON web token) valido emesso dallo stesso issuer. Questa soluzione è corretta quando i client API ricevono già i token dal provider. In alternativa, escludere il percorso:

skip_auth_routes = [
  "^/api/",
  "POST=^/webhook/",
  "GET=^/healthz$"
]

Ogni valore è un'espressione regolare confrontata con il percorso normalizzato, eventualmente preceduta da un metodo HTTP e =. POST=^/webhook/ lascia aperto il ricevitore webhook alle richieste POST, mentre un utente che apre lo stesso percorso nel browser viene comunque indirizzato al login. Ogni voce crea una breccia nel controllo di accesso. Per questo, ancorare le espressioni con ^ e mantenerle il più restrittive possibile in base a quanto consente il client.

I websocket sono il caso in cui si commettono più errori. La richiesta di upgrade è una normale richiesta HTTP GET che trasporta gli stessi cookie delle altre richieste. Di norma supera quindi il controllo e non richiede eccezioni. Il problema riguarda il proxying della connessione. Senza gli header Upgrade e Connection nella location protetta, l'upgrade non viene completato e il client dell'applicazione ritenta continuamente, mostrando un messaggio WebSocket connection ... failed nella console del browser. Escludere il percorso non risolve il problema, perché la richiesta era già stata autorizzata.

Esiste tuttavia un limite concreto. Il controllo viene eseguito una sola volta, durante l'upgrade. Un websocket che rimane aperto per ore non viene più verificato. Di conseguenza, rimuovere un utente dal provider non chiude il socket già aperto da quell'utente. Riavviare l'applicazione per interrompere le connessioni attive.

Per impostazione predefinita, l'intera sessione viene memorizzata nel cookie e cifrata con il tuo cookie_secret. In questo modo oauth2-proxy rimane stateless e non richiede servizi aggiuntivi. Esiste però un limite, perché i browser impongono a un cookie una dimensione massima di circa 4 KB. Quando l'ID token contiene un elenco lungo di claim relativi ai gruppi, oauth2-proxy suddivide la sessione tra _oauth2_proxy_0, _oauth2_proxy_1 e i cookie successivi. Dopo alcune parti, gli header della richiesta diventano abbastanza grandi da far rispondere nginx con 400 Request Header Or Cookie Too Large prima che l'applicazione possa ricevere la richiesta.

In questo caso, sposta la sessione sul server:

session_store_type = "redis"
redis_connection_url = "redis://127.0.0.1:6379"

Il browser conserva quindi un ticket breve, mentre la sessione cifrata viene memorizzata in Redis. Il costo è un servizio che deve rimanere attivo: se Redis si arresta, tutte le sessioni diventano non valide e tutti gli utenti vengono disconnessi contemporaneamente. Anche il cookie store ha un limite: due richieste che aggiornano la stessa sessione nello stesso momento possono entrare in conflitto e forzare un nuovo accesso.

Cosa non offre l'autenticazione forward auth

Questo è un controllo all'ingresso. Non è un'autorizzazione interna all'applicazione, e questa differenza determina se l'approccio è adatto al tuo caso.

Dopo l'accesso, l'applicazione vede ciò che vedeva prima. Se l'applicazione dispone di ruoli propri, forward auth non li assegna, a meno che l'applicazione supporti l'autenticazione basata su header e associ un header a un account. Grafana lo supporta tramite le impostazioni auth.proxy. La maggior parte delle applicazioni self-hosted non lo supporta. Di conseguenza, per l'applicazione tutti gli utenti che superano il controllo sono la stessa identità, che spesso è un amministratore.

Inoltre, forward auth non protegge i token API dell'applicazione. Un personal access token rilasciato dall'applicazione autentica direttamente verso l'applicazione, non verso oauth2-proxy. Il token smette quindi di funzionare non appena il controllo viene posto davanti all'applicazione. Escludi il percorso API per ripristinarne il funzionamento, ma in questo modo quel token diventa l'unica protezione del percorso. Ora gestisci due sistemi di autenticazione per un unico servizio, e SSO copre soltanto uno dei due.

La revoca è il terzo limite. L'eliminazione di un utente dal provider impedisce i nuovi accessi e interrompe il rinnovo del token eseguito da cookie_refresh, ma un cookie di sessione già esistente resta valido fino alla scadenza. Per impostazione predefinita, cookie_expire è 168 hours, cioè una settimana di accesso per un utente appena rimosso. Imposta cookie_refresh su un valore breve, ad esempio un'ora, in modo che la revoca diventi effettiva entro quella finestra.

Anche la traccia di audit si interrompe al controllo. oauth2-proxy registra chi è passato e quando. L'applicazione registra una sessione senza nome. Se devi stabilire chi ha modificato un'impostazione, l'identità tramite header nell'applicazione è il requisito minimo. Account distinti per ogni utente sono la soluzione corretta.

Quando conviene pagare per il livello SSO

L'autenticazione delegata è lo strumento giusto quando un'applicazione non dispone di alcun accesso o usa una password condivisa e si vuole centralizzare la gestione degli utenti. Richiede un pomeriggio di lavoro e un processo aggiuntivo, e funziona con qualsiasi applicazione che comunichi tramite HTTP.

È lo strumento sbagliato quando utenti diversi devono avere autorizzazioni diverse all'interno della stessa applicazione. Un controllo di accesso non può esprimere che «Ana può modificare i dashboard e Bo può solo consultarli». Se il fornitore vende un livello SSO, la mappatura tra gruppi e ruoli è solitamente il vero elemento acquistato; ricrearla con header e regole del proxy è più fragile che pagare per questa funzionalità. Vale la pena leggere Il modello di prezzo alla base di questi livelli SSO prima di decidere.

Anche altre due situazioni portano alla stessa conclusione. Le attività di conformità che richiedono registri di audit per singolo utente all'interno dell'applicazione non accetteranno il log degli accessi del proxy come prova. Inoltre, qualsiasi applicazione con un client mobile o desktop che non conserva i cookie del browser ostacolerà il controllo di accesso a ogni richiesta.

FAQ

Che cos’è l’autenticazione forward?

L’autenticazione forward è un modello in cui il reverse proxy interroga un servizio di autenticazione separato per ogni richiesta in ingresso prima di inoltrarla al servizio upstream. Il proxy invia gli header della richiesta a un endpoint come /oauth2/auth e legge il codice di stato. 202 significa che la richiesta è autorizzata, quindi la richiesta originale viene inoltrata all’applicazione. 401 significa che non esiste una sessione, quindi il proxy reindirizza il browser alla pagina di accesso. Nginx la implementa con la direttiva auth_request, Traefik con il middleware forwardAuth e Caddy con forward_auth.

Perché oauth2-proxy mi reindirizza alla pagina di accesso in un loop?

La richiesta di callback ha raggiunto oauth2-proxy senza il cookie CSRF, quindi oauth2-proxy riavvia il flusso. Il log del server contiene No cookies were found in OAuth callback. e il browser mostra Login Failed: Unable to find a valid CSRF token. Please try again.. La causa più comune è cookie_secure = true su un sito raggiunto dal browser tramite HTTP non cifrato, perché un browser non memorizza un cookie Secure su un’origine http://. La seconda causa più comune è un valore cookie_domains che non include l’hostname visualizzato nella barra degli indirizzi.

Come posso consentire il passaggio di un client API o di un webhook attraverso oauth2-proxy?

Usa skip_auth_routes con un’espressione regolare ancorata, facoltativamente limitata a un solo metodo HTTP, ad esempio POST=^/webhook/. Se i client API dispongono già di JWT emessi dallo stesso provider, skip_jwt_bearer_tokens = true accetta questi token al posto di un cookie e mantiene protetto il percorso. Tutto ciò che è elencato in skip_auth_routes non richiede autenticazione per nessuno, quindi mantieni ogni espressione quanto più restrittiva possibile in base alle esigenze del chiamante.

oauth2-proxy assegna all’applicazione autorizzazioni specifiche per ogni utente?

No. È un punto di controllo, non un sistema di autorizzazione. Decide chi può raggiungere l’applicazione, ma tutti gli utenti che la raggiungono risultano identici all’applicazione, a meno che questa non legga gli header di identità e non li associ agli account. Grafana può farlo tramite le impostazioni auth.proxy. La maggior parte delle applicazioni self-hosted non supporta questa funzione, quindi tutte le persone che superano il controllo condividono l’unica identità con cui è in esecuzione l’applicazione.

È possibile aggirare oauth2-proxy impostando direttamente l’header di identità?

Sì, se è possibile raggiungere direttamente l’applicazione. L’identità arriva come un normale header, ad esempio X-Auth-Request-Email, e l’applicazione si fida di ciò che riceve. Chiunque possa aprire una connessione alla porta dell’applicazione può inviare quell’header e impersonare qualsiasi utente. Associa l’applicazione a 127.0.0.1, oppure mantienila su una rete Docker interna senza porte pubblicate, e verifica la configurazione con sudo ss -tlnp.

#oauth2-proxy#sso#oidc#reverse-proxy#forward-auth