SSD Nodes Learn 🎉 VPS $5.50/aydan başlayan
Rehberler Matt ConnorYazan Matt Connor · Güncellendi 2026-08-21

oauth2-proxy ile uygulamalara SSO nasıl eklenir?

Giriş özelliği olmayan uygulamalarınızı oauth2-proxy kullanarak OIDC sağlayıcınızla koruyun. Nginx veya Traefik üzerinde forward auth yapılandırmasını hatasız kurun.

Forward auth: Giriş özelliği olmayan bir uygulamaya SSO kazandırma

oauth2-proxy, kendi giriş mekanizması bulunmayan bir uygulamaya tek oturum açma (SSO) özelliği sağlar. Bu yapı, uygulamanın önündeki reverse proxy'nin her isteği durdurması, oauth2-proxy'ye isteğin geçerli bir oturum taşıyıp taşımadığını sorması ve yalnızca yanıt olumlu olduğunda isteği yukarı akışa (upstream) iletmesi prensibiyle çalışır. Uygulama kodu hiçbir değişikliğe uğramaz çünkü uygulama bu denetimden haberdar olmaz.

Denetim işlemi, fazladan bir HTTP isteği ile gerçekleşir. Proxy, gelen istek başlıklarının bir kopyasını /oauth2/auth adresine gönderir ve dönen durum kodunu okur. 202 kodu, çağrıyı yapanın bir oturumu olduğu anlamına gelir; bu durumda proxy, orijinal isteği uygulamaya iletir. 401 kodu ise oturum olmadığını belirtir; bu durumda proxy, tarayıcıyı kimlik sağlayıcınızda bir OpenID Connect (OIDC) giriş süreci başlatan /oauth2/sign_in adresine yönlendirir. OIDC, OAuth 2.0 üzerine inşa edilmiş kimlik katmanıdır ve sağlayıcı, giriş işlemleri için halihazırda kullandığınız herhangi bir servistir.

Bu desenin her reverse proxy yazılımında bir karşılığı vardır. Nginx bu direktifi auth_request olarak adlandırır. Traefik, bu middleware'i forwardAuth olarak tanımlar. Caddy ise bunu forward_auth şeklinde ifade eder. Alt isteği yanıtlayan servis de değiştirilebilir niteliktedir. oauth2-proxy, standart OIDC protokolünü desteklediği ve kendi veritabanına ihtiyaç duymadığı için yaygın olarak tercih edilir.

Yapılandırmayı yazmadan önce güven sınırını belirleyin

Başarılı bir kontrolden sonra oauth2-proxy, kimlik bilgilerini yanıt başlıkları olarak döndürür ve reverse proxy bunları upstream isteğine kopyalar. set_xauthrequest etkinleştirildiğinde X-Auth-Request-User ve X-Auth-Request-Email elde edersiniz. Uygulama bu başlıkları okur ve onlara güvenir.

Tüm güvenlik modeli bundan ibarettir, bu yüzden sonucunu açıkça ifade edin. Uygulama portuna TCP bağlantısı açabilen herhangi bir şey, bu başlıkları kendisi ayarlayabilir ve herhangi bir kullanıcı kimliğine bürünebilir. Tek bir curl -H "X-Auth-Request-Email: admin@example.com" http://app-host:3000/, uygulamaya doğrudan ulaşması durumunda tam bir güvenlik atlatmasıdır.

Bu nedenle uygulama, proxy dışında hiçbir yerden erişilebilir olmamalıdır. Docker Compose içinde, uygulama servisinden ports: eşlemesini silin ve onu sadece proxy container'ının erişebileceği şekilde dahili ağda bırakın. Çıplak bir sunucuda ise uygulamayı 0.0.0.0:3000 yerine 127.0.0.1:3000 adresine bağlayın. Ardından gerçekte neyi dışarıya açtığınızı kontrol edin:

sudo ss -tlnp | grep 3000

0.0.0.0:3000 yazan bir satır, uygulamanın genel IP adresi üzerinden yanıt verdiğini ve kapınızın sadece süs olduğunu gösterir. 127.0.0.1:3000 olması gereken durumdur. Bir güvenlik duvarı kuralı faydalı bir ikinci katmandır, ancak bağlama adresi, kurallar kümenizi temizleyen başka bir araçtan etkilenmeden varlığını sürdüren tek yöntemdir.

oauth2-proxy kurulumu

Ağustos 2026 itibarıyla güncel sürüm, Haziran 2026'da yayınlanan v7.15.3'tür. İkili dosyayı kurun ve indirme işlemini doğrulayın:

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, OK ile biten bir satır çıktısı vermelidir. Eğer FAILED çıktısını veriyorsa, işlemi durdurun ve ikili dosyayı çalıştırmak yerine yeniden indirin.

Docker tarafında imaj quay.io/oauth2-proxy/oauth2-proxy şeklindedir ve etiket sürümünü sabitlemeniz gerekir: quay.io/oauth2-proxy/oauth2-proxy:v7.15.3. Etiketi latest olarak bırakmak, rutin bir docker compose pull işlemini sunucudaki tüm uygulamaları koruyan tek sürecin plansız bir yükseltmesine dönüştürür.

Oturum çerezi şifrelenmiştir ve cookie_secret bu işlem için kullanılan anahtardır. Bu değer tam olarak 16, 24 veya 32 bayt uzunluğunda olmalıdır; çünkü AES (advanced encryption standard) anahtarı olarak kullanılır. Başka bir uzunlukta oauth2-proxy çalışmayı reddeder ve başlangıç hatasında cookie secret ile ilgili bir uyarı verir.

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

tr kullanımı görsel bir tercih değildir. Standart base64 formatını URL uyumlu alfabeye dönüştürür; böylece değer, tırnak işareti sorunları yaşamadan bir kabuk (shell), bir ortam dosyası ve bir HTTP başlığı içerisinde bozulmadan iletilebilir.

Bu değer için iki kural geçerlidir. Her dağıtım için farklı bir secret kullanın. Aynı alan adı arkasında birden fazla oauth2-proxy örneği çalıştırıyorsanız, hepsine aynı secret değerini atayın; çünkü bir örnek tarafından şifrelenen çerezin diğerleri tarafından okunabilmesi gerekir.

oauth2-proxy yapılandırmasını yazma

İstemci gizli anahtarının (client secret) ps çıktısında görünmemesi için ayarları uzun bir komut satırı yerine bir dosyada tutun.

# /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, oauth2-proxy'ye önündeki proxy'den gelen X-Forwarded-* başlıklarına güvenmesini söyler. Bu ayar olmadan oauth2-proxy, proxy'nin kendi adresini istemci adresi olarak görür ve isteğin HTTPS üzerinden gelip gelmediğini yanlış değerlendirebilir.

upstreams = ["static://202"], oauth2-proxy'nin kimliği doğrulanmış bir isteğe 202 yanıtı vermesini ve hiçbir şeyi proxy'lememesini sağlar; reverse proxy zaten proxy işlemini gerçekleştirdiği için forward auth için gereken tam olarak budur. Diğer dağıtım biçimi, oauth2-proxy'yi upstreams = ["http://127.0.0.1:3000"] ile ve hiçbir auth_request olmadan doğrudan istek yoluna yerleştirir. Bu yöntem tek bir uygulama için daha basittir ancak on uygulama için ölçeklenemez.

email_domains = ["*"], sağlayıcınızın kimliğini doğrulayacağı her adresi kabul eder. Bu ayarı kendi alan adınızla sınırlandırın veya daha iyisi, erişimi sağlayıcı tarafında bir grup atamasıyla kısıtlayın; çünkü kullanıcıları zaten yönettiğiniz yer orasıdır.

Servisi systemd altında kendi kullanıcısıyla çalıştırın:

# /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

/ping çıktısının OK yazdırması, sürecin başladığını ve yapılandırmasını yüklediğini gösterir. Bu, oauth2-proxy'nin kendi sağlık kontrolü uç noktasıdır ve hiçbir zaman oturum istemez. Eğer hiçbir yanıt gelmiyorsa journalctl -u oauth2-proxy -n 50 dosyasını okuyun; hatalı bir sağlayıcı URL'si veya yanlış uzunlukta bir çerez gizli anahtarı başlangıçta başarısızlığa neden olur ve her ikisi de bu dosyada belirtilir.

Yönlendirme URI'sini sağlayıcınızda kaydedin

Sağlayıcınızda bir OIDC uygulaması oluşturun ve yönlendirme URI'sini yapılandırmadaki redirect_url ile tam olarak eşleşecek şekilde ayarlayın: https://app.example.com/oauth2/callback. "Tam olarak" ifadesi; şema, ana makine, port ve yolun karakteri karakterine aynı olması gerektiği anlamına gelir. Sondaki bir eğik çizgi (slash), URI'yi farklı kılar.

Bu durum, tüm kurulum sürecindeki en yaygın hata kaynağıdır ve oauth2-proxy devreye girmeden önce başarısız olur. Sağlayıcı, yetkilendirme isteğini reddeder ve kendi hata sayfasını görüntüler; bu nedenle oauth2-proxy günlüklerinde hiçbir şey görünmez. Bunun belirtisi adres çubuğudur: tarayıcı hala sağlayıcınızın alan adındadır ve sorgu dizisi doğrudan error=invalid_request değerini veya redirect_uri sayfa adlarını taşır. Bunu gördüğünüzde, proxy yapılandırmasını değil, sağlayıcıdaki uygulama kaydını düzeltin.

Sağlayıcı URL'sini elle yazmak yerine kopyalayın. oauth2-proxy, oidc_issuer_url adresine /.well-known/openid-configuration ekler ve başlangıçta bu keşif belgesini getirir. Önce kendiniz kontrol edin:

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

authorization_endpoint anahtarını içeren bir JSON, sağlayıcı URL'sinin doğru olduğu anlamına gelir. 404 veya bir HTML hata sayfası, URL'nin yanlış olduğu anlamına gelir ve oauth2-proxy aynı 404 hatasıyla başlamayacaktır. Henüz bir sağlayıcı seçmediyseniz, Keycloak, Authentik ve Zitadel karşılaştırması avantaj ve dezavantajları ele alır; Authentik'i kendi SSO sunucunuz olarak çalıştırma rehberi ise bu kurulumun sağlayıcı tarafındaki adımlarını açıklar.

Nginx: auth_request

Nginx, auth_request ile ileri yönlendirmeli kimlik doğrulama (forward auth) gerçekleştirir; bu mekanizma dahili bir alt istek tetikler ve dönen durum koduna göre dallanır.

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

Buradaki üç ayrıntı kritik öneme sahiptir. Boş bir Content-Length değerine sahip proxy_pass_request_body off, nginx'in her POST isteğinin gövdesini alt isteğe kopyalamasını engeller; bu durum, oauth2-proxy verinin hiçbir kısmını okumadığı için önemlidir. Dosya yükleme işlemlerinde varsayılan davranış, dosyanın iki kez gönderilmesine neden olur.

auth_request_set $auth_cookie ve add_header Set-Cookie ikilisi, yenilenen oturum çerezini tarayıcıya geri iletir. Bu ayar çıkarılırsa cookie_refresh sessizce hiçbir işlem yapmaz; çünkü nginx alt isteğin Set-Cookie değerini atar ve tarayıcı, oturum süresi dolana kadar eski değeri tutmaya devam eder.

error_page 401 = @oauth2_signin, başarısız bir kontrolü giriş sayfasına yönlendirmeye dönüştüren kısımdır. Bu ayar olmadan, kimliği doğrulanmamış bir ziyaretçi boş bir 401 Authorization Required sayfası ile karşılaşır ve ilerleyemez.

Yeniden yükleme yapmadan önce her zaman test edin:

sudo nginx -t && sudo systemctl reload nginx

Çevredeki yönergeler sizin için yeniyse, nginx reverse proxy yapılandırmasının anatomisi bu katmanın altındaki yapıyı açıklar.

Traefik: forwardAuth ara katmanı

Traefik'in aynı iş için iki ara katmana (middleware) ihtiyacı vardır. Biri kontrolü gerçekleştirir. Diğeri ise 401 hata kodunu tarayıcı yönlendirmesine dönüştürür.

# 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

Her iki ara katmanı da uygulamanızın önündeki yönlendiriciye (router) bağlayın ve oauth2-proxy'yi kendi yönlendiricisi üzerinde oauth.example.com adresinde yayınlayın. Bunun nedeni, tarayıcının kontrolü geçmeden /oauth2/sign_in ve /oauth2/callback adreslerine ulaşabilmesi gerekliliğidir.

statusRewrites 401 hata kodunu 302 yönlendirmesine eşlemek, genellikle gözden kaçan kısımdır. Bu işlem yapılmazsa Traefik, oturum açma yönlendirmesini 401 durumuyla döndürür; tarayıcı bunu takip etmez ve ziyaretçi yalnızca Found. kelimesini içeren bir sayfa görür.

trustForwardHeader: true, orijinal ana bilgisayar (host) ve URI bilgilerini oauth2-proxy'ye iletir. oauth2-proxy, kullanıcının talep ettiği sayfaya geri dönmesini sağlayan rd değerini oluşturmak için bu bilgilere ihtiyaç duyar. whitelist_domains ayarını bu ana bilgisayarı da kapsayacak şekilde yapılandırın; aksi takdirde oauth2-proxy, açık yönlendirme (open-redirect) riski nedeniyle rd parametresini düşürür ve kullanıcılar giriş yaptıktan sonra / adresine yönlendirilir. Bir Traefik sunucusu genellikle aynı anda birden fazla uygulamanın önünde yer alır ve birden fazla Docker Compose uygulamasını tek bir Traefik örneği üzerinden yönlendirme konusu, bu yapının nasıl entegre edileceğini gösterir.

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

Burada sıralama önemlidir. /oauth2/* bloğu önce gelir ve herhangi bir forward_auth içermez; çünkü oturum açmamış bir ziyaretçinin giriş ve geri çağırma (callback) yollarına erişebilmesi gerekir. Kontrol mekanizmasını bu yolların önüne koyarsanız, tarayıcı pes edene kadar giriş sayfası kendi kendine yönlendirme yapacaktır.

copy_headers, kimlik bilgilerini upstream isteğine aktaran kısımdır ve yalnızca oauth2-proxy set_xauthrequest = true ile çalıştırıldığında değer üretir. Hangi proxy'nin seçileceği ayrı bir konudur ve nginx, Caddy ve Traefik karşılaştırması bu konuyu detaylıca ele alır.

Oturum açma işlemi neden sürekli giriş sayfasına dönüyor?

Sağlayıcı üzerinde oturum açarsınız, sizi geri yönlendirir ve oauth2-proxy sizi doğrudan tekrar sağlayıcıya gönderir. Bu döngü, geri çağırma (callback) isteğinin, oauth2-proxy tarafından çıkışta ayarlanan çerez olmadan ulaştığı anlamına gelir. Günlük kayıtlarında bu durum şu şekilde belirtilir:

No cookies were found in OAuth callback.

veya başka bir çerez ulaştığı halde doğru olan ulaşmadığında:

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

CSRF, siteler arası istek sahteciliği (cross-site request forgery) anlamına gelir; bu çerez, geri çağırma işleminin onu başlatan oturum açma isteğiyle ilişkilendirilebilmesi için mevcuttur. Tarayıcı aynı hatayı şu şekilde görür:

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

Bu dört nedeni sırasıyla kontrol edin.

  1. cookie_secure = true ayarı etkinken tarayıcının siteye düz HTTP üzerinden ulaşması. Tarayıcı, Secure olarak işaretlenmiş bir çerezi http:// bir kaynakta saklamaz, bu nedenle çerez asla geri gönderilmez. TLS (transport layer security) sonlandırmasını düzgün yapılandırın veya yalnızca localhost üzerinde test yaparken cookie_secure = false ayarını kullanın.
  2. Adres çubuğundaki ana bilgisayar adını (hostname) kapsamayan bir cookie_domains değeri. .example.com değeri app.example.com için geçerlidir ancak app.example.net için hiçbir işlev görmez.
  3. Tarayıcının çerezi reddetmesi. Sıkı bir gizlilik eklentisi veya üçüncü taraf çerez engelleme özelliği, giden yönlendirme ile geri çağırma arasındaki _oauth2_proxy_csrf çerezini silebilir.
  4. Saat sapması. Sunucu saati ile sağlayıcının saati arasında büyük fark varsa, kimlik belirtecinin (ID token) iat ve exp değerleri kabul edilen zaman aralığının dışında kalır ve oturum ulaştığı anda reddedilir. timedatectl bu durumda System clock synchronized: yes hatasını raporlamalıdır.

Tahmin yürütmek yerine durumu sunucu tarafından izleyin:

sudo journalctl -u oauth2-proxy -f

Uygulamayı gizli sekmede açın. Her istek durumuyla birlikte günlüğe kaydedilir; bu nedenle, hemen ardından sağlayıcıya başka bir yönlendirmenin geldiği bir geri çağırma işlemi, kayıtlardaki döngüyü doğrular.

Oturum açma işlemini atlaması gereken yollar: API'ler, webhook'lar ve websocket'ler

Forward auth, çerez tutan bir tarayıcı varsayar. Tarayıcısı olmayan istemciler bu yapıda çalışmaz.

Authorization: Bearer <token> gönderen bir API istemcisinin çerezi yoktur; bu nedenle sağlayıcınızın oturum açma sayfasına 302 yönlendirmesi alır ve ardından HTML içeriğini JSON olarak ayrıştırmaya çalışır. Bunun için iki temiz çözüm mevcuttur. skip_jwt_bearer_tokens = true ayarını yapmak, oauth2-proxy'nin aynı sağlayıcıdan gelen geçerli bir JWT (JSON web token) bearer token'ını kabul etmesini sağlar; API istemcileriniz zaten sağlayıcıdan token alıyorsa bu doğru yöntemdir. Aksi takdirde, ilgili yolu muaf tutun:

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

Her değer, normalleştirilmiş yolla eşleştirilen bir düzenli ifadedir (regex); isteğe bağlı olarak bir HTTP metodu ve = ile ön eklenebilir. POST=^/webhook/, webhook alıcısını POST isteklerine açık bırakırken, aynı yola giden bir kullanıcıyı oturum açma sayfasına yönlendirmeye devam eder. Her girdi güvenlik kapınızda bir delik oluşturur; bu nedenle ifadeleri ^ ile sabitleyin ve onları istemcinin izin verdiği ölçüde dar tutun.

Websocket'ler insanların en çok hata yaptığı konudur. Yükseltme (upgrade) isteği, diğer tüm isteklerle aynı çerezleri taşıyan sıradan bir HTTP GET isteğidir; bu nedenle kontrolü normal şekilde geçer ve muafiyet gerektirmez. Sorun, bu isteği çevreleyen proxy yapılandırmasından kaynaklanır. Korunan konumda Upgrade ve Connection başlıkları bulunmazsa, yükseltme işlemi asla tamamlanmaz ve uygulamanın istemcisi tarayıcı konsolunda bir WebSocket connection ... failed mesajı ile sürekli yeniden deneme yapar. İsteğin yetkilendirmesi zaten yapılmış olduğundan, yolu muaf tutmak bu sorunu çözmez.

Gerçek bir sınırlama mevcuttur. Kontrol, yükseltme sırasında yalnızca bir kez çalışır. Saatlerce açık kalan bir websocket asla yeniden kontrol edilmez; bu nedenle sağlayıcınızdan bir kullanıcıyı silmek, kullanıcının elinde tuttuğu mevcut soketi kapatmaz. Canlı bağlantıları kesmek için uygulamayı yeniden başlatın.

Oturum depolama ve aşırı büyüyen çerezler

Varsayılan olarak tüm oturum, cookie_secret ile şifrelenmiş şekilde çerez içinde tutulur. Bu durum oauth2-proxy uygulamasının durumsuz (stateless) kalmasını sağlar ve ek bir servis gerektirmez. Ancak tarayıcılar çerez boyutunu yaklaşık 4 KB ile sınırladığından bu yöntemin bir üst sınırı vardır. ID token uzun bir grup talebi listesi taşıdığında, oauth2-proxy oturumu _oauth2_proxy_0, _oauth2_proxy_1 ve devamı parçalara böler. Parça sayısı arttığında istek başlıkları o kadar büyür ki, istek uygulamaya ulaşmadan önce nginx 400 Request Header Or Cookie Too Large hatası döndürür.

Bu durum gerçekleştiğinde oturumu sunucu tarafına taşıyın:

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

Bu durumda tarayıcı kısa bir bilet tutar ve şifrelenmiş oturum Redis üzerinde saklanır. Bunun maliyeti, sürekli çalışması gereken bir servistir: Redis çökerse tüm oturumlar geçersiz hale gelir ve tüm kullanıcıların oturumu aynı anda kapatılır. Çerez depolama yönteminin kendi maliyeti ise, aynı oturumu aynı anda yenileyen iki isteğin çakışarak kullanıcıyı yeniden giriş yapmaya zorlayabilmesidir.

Forward auth size ne sağlamaz

Bu, kapıdaki bir güvenlik geçididir. Uygulama içindeki yetkilendirme mekanizması değildir; bu ayrım, yaklaşımın durumunuza uygun olup olmadığını belirler.

Kullanıcı geçitten geçtiğinde, uygulama her zaman gördüğü şeyi görmeye devam eder. Uygulamanın kendi rol sistemi varsa, uygulama başlık tabanlı kimlik doğrulamayı desteklemediği ve bir başlığı hesapla eşleştirmediği sürece forward auth bu rolleri doldurmaz. Grafana, auth.proxy ayarları aracılığıyla bunu yapar. Çoğu self-hosted uygulama bunu desteklemez; bu nedenle geçitten geçen herkes uygulama için aynı tek kimlik olarak görünür ve bu kimlik genellikle yönetici yetkilerine sahiptir.

Ayrıca bu yöntem, uygulamanın kendi API token'larını korumaz. Uygulama tarafından verilen kişisel erişim token'ı, oauth2-proxy'ye değil doğrudan uygulamaya kimlik doğrulaması yapar; bu nedenle geçit önüne yerleştirildiği anda token çalışmayı durdurur. API yolunu muaf tutarak token'ı tekrar çalışır hale getirdiğinizde, o yolu koruyan tek şey söz konusu token olur. Artık tek bir servis üzerinde iki farklı kimlik doğrulama sistemi çalıştırıyorsunuz demektir ve SSO bunlardan yalnızca birini kapsar.

Yetki iptali üçüncü eksikliktir. Sağlayıcınızda bir kullanıcıyı silmek, yeni girişleri ve cookie_refresh tarafından gerçekleştirilen token yenileme işlemini durdurur; ancak mevcut bir oturum çerezi süresi dolana kadar geçerli kalır. cookie_expire varsayılan olarak 168 saattir; bu da yeni sildiğiniz birine bir haftalık erişim hakkı tanımak anlamına gelir. Yetki iptalinin bu süre zarfında gerçekleşmesi için cookie_refresh değerini bir saat gibi kısa bir süreye ayarlayın.

Denetim izi de geçitte son bulur. oauth2-proxy kimin ne zaman geçtiğini günlüğe kaydeder. Uygulama ise isimsiz bir oturumu günlüğe kaydeder. Bir ayarı kimin değiştirdiğini tespit etmeniz gerekiyorsa, uygulamada başlık tabanlı kimlik bilgisi minimum gerekliliktir; gerçek kullanıcı bazlı hesaplar ise en güvenilir çözümdür.

SSO ücretini ödemenin daha mantıklı olduğu durumlar

Uygulamanın hiçbir giriş sistemi yoksa veya tek bir ortak parola kullanılıyorsa ve kullanıcıları tek bir merkezden ekleyip çıkarmak istiyorsanız, forward auth doğru araçtır. Bu yöntem bir öğleden sonranızı alır, fazladan bir süreç gerektirir ancak HTTP ile haberleşen her uygulama ile çalışır.

Aynı uygulama içinde farklı kişilerin farklı izinlere sahip olması gerektiği durumlarda ise yanlış araçtır. Bir geçit (gate), "Ana panelleri düzenleyebilir, Bo ise sadece okuyabilir" gibi bir kuralı ifade edemez. Eğer yazılım sağlayıcısı bir SSO katmanı satıyorsa, aslında satın aldığınız şey genellikle grup-rol eşleme özelliğidir; bunu başlıklar (headers) ve proxy kuralları ile yeniden oluşturmak, ücretini ödemekten daha kırılgan bir yapıdır. Karar vermeden önce SSO katmanlarının arkasındaki fiyatlandırma modeli başlıklı yazıyı okumak faydalı olacaktır.

Diğer iki durum da aynı yöne işaret eder. Uygulama içinde kullanıcı bazlı denetim kayıtlarına ihtiyaç duyan uyumluluk çalışmaları, proxy erişim günlüğünü kanıt olarak kabul etmeyecektir. Ayrıca tarayıcı çerezlerini taşımayan mobil veya masaüstü istemcisine sahip herhangi bir uygulama, her istekte geçit ile sorun yaşayacaktır.

FAQ

Forward auth nedir?

Forward auth, reverse proxy'nin gelen her isteği yukarı akışa (upstream) iletmeden önce ayrı bir kimlik doğrulama servisine sorduğu bir yöntemdir. Proxy, istek başlıklarını /oauth2/auth gibi bir uç noktaya gönderir ve dönen durum kodunu okur. 202 kodu isteğin onaylandığı anlamına gelir ve orijinal istek uygulamaya iletilir. 401 kodu oturumun olmadığını belirtir; bu durumda proxy, tarayıcıyı bir giriş sayfasına yönlendirir. Nginx bu işlemi auth_request yönergesiyle, Traefik forwardAuth ara katman yazılımıyla (middleware), Caddy ise forward_auth ile gerçekleştirir.

oauth2-proxy beni neden sürekli giriş sayfasına yönlendiriyor?

Geri çağırma (callback) isteği, CSRF çerezi olmadan oauth2-proxy'ye ulaştığı için oauth2-proxy süreci baştan başlatır. Sunucu günlüğünde No cookies were found in OAuth callback. mesajı görünür ve tarayıcıda Login Failed: Unable to find a valid CSRF token. Please try again. hatası oluşur. Bunun yaygın nedeni, tarayıcının http:// kökenli bir adreste Secure çerezini saklamayacak olması nedeniyle, düz HTTP üzerinden ulaşılan bir sitede cookie_secure = true kullanılmasıdır. Bir diğer yaygın neden ise adres çubuğundaki ana bilgisayar adını (hostname) kapsamayan bir cookie_domains değeridir.

Bir API istemcisine veya webhook'a oauth2-proxy üzerinden nasıl izin veririm?

İsteğe bağlı olarak tek bir HTTP metoduna kısıtlanmış, çapalanmış bir düzenli ifade (regular expression) ile skip_auth_routes kullanın; örneğin POST=^/webhook/. API istemcileriniz aynı sağlayıcı tarafından verilmiş JWT'lere zaten sahipse, skip_jwt_bearer_tokens = true bu belirteçleri çerez yerine kabul eder ve yolu korumaya devam eder. skip_auth_routes içinde listelenen her şey herkes için kimlik doğrulaması gerektirmez, bu nedenle her ifadeyi arayanın izin verdiği ölçüde dar tutun.

oauth2-proxy uygulamaya kullanıcı bazlı yetkiler sağlar mı?

Hayır. Bu bir yetkilendirme sistemi değil, bir kapıdır. Uygulamaya kimin ulaşacağına karar verir; uygulama kimlik başlıklarını okuyup bunları hesaplarla eşleştirmediği sürece, uygulamaya ulaşan herkes uygulama için aynı görünür. Grafana bunu auth.proxy ayarları aracılığıyla yapabilir. Çoğu self-hosted uygulama bunu yapamaz, bu nedenle kapıdan geçen herkes uygulamanın çalıştığı tek bir kimliği paylaşır.

Birisi kimlik başlığını kendisi ayarlayarak oauth2-proxy'yi atlatabilir mi?

Evet, uygulamaya doğrudan ulaşabiliyorsa atlatabilir. Kimlik bilgisi, X-Auth-Request-Email gibi düz bir başlık olarak gelir ve uygulama aldığı her şeye güvenir. Uygulama portuna bağlantı açabilen herkes bu başlığı göndererek herhangi bir kullanıcı gibi davranabilir. Uygulamayı 127.0.0.1 adresine bağlayın veya yayınlanmış bir portu olmayan dahili bir Docker ağında tutun ve bunu sudo ss -tlnp ile doğrulayın.

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