Nginx ile OAuth2 Proxy Entegrasyonu: Merkezi Kimlik Doğrulama Yapılandırması
Modern web uygulamalarında kimlik doğrulama, her servis için ayrı ayrı implemente etmek yerine merkezi bir noktada yönetmek hem güvenlik hem de bakım açısından büyük avantaj sağlar. Nginx ile OAuth2 Proxy entegrasyonu tam da bu ihtiyacı karşılar: tek bir yapılandırma noktasından tüm backend servislerinizi kimlik doğrulama koruması altına alabilirsiniz. Bu yazıda, gerçek dünya senaryolarıyla bu entegrasyonu nasıl kuracağınızı ve yöneteceğinizi adım adım ele alacağız.
OAuth2 Proxy Nedir ve Neden Kullanmalıyız?
OAuth2 Proxy, Bitly tarafından geliştirilen ve sonradan topluluk tarafından sürdürülen açık kaynaklı bir reverse proxy uygulamasıdır. Temel işlevi, korunan kaynaklara erişimi OAuth2/OIDC protokolü üzerinden doğrulanmış kullanıcılarla sınırlandırmaktır. Google, GitHub, GitLab, Keycloak, Azure AD gibi onlarca identity provider ile çalışabilir.
Klasik senaryoda şöyle düşünün: Şirketinizde Grafana, Kibana, Prometheus ve birkaç internal servis var. Her biri için ayrı authentication mekanizması kurmak yerine, Nginx’in önüne OAuth2 Proxy koyarak tüm bu servislere erişimi tek merkezden kontrol edebilirsiniz. Kullanıcı bir kez Google veya Keycloak üzerinden giriş yapar, token cookie olarak saklanır ve tüm korunan servislere erişim sağlanır.
Mimari Yapı
Sistemin çalışma mantığını anlamak, yapılandırmayı doğru yapmak için kritik. Trafik akışı şu şekilde işler:
- Kullanıcı korunan bir URL’ye istek gönderir
- Nginx bu isteği
auth_requestdirektifi ile OAuth2 Proxy’e yönlendirir - OAuth2 Proxy token’ı doğrular, geçerliyse 200 döner
- Token yoksa veya geçersizse 401/302 döner ve kullanıcı login sayfasına yönlendirilir
- Nginx 200 aldıktan sonra isteği backend servise iletir
Bu mimari sayesinde backend servisleriniz authentication’dan tamamen haberdar olmak zorunda kalmaz.
Kurulum Ortamı Hazırlama
Önce sistemimizi hazırlayalım. Ubuntu 22.04 üzerinde çalışıyoruz ancak adımların büyük çoğunluğu diğer dağıtımlarda da geçerli.
# Nginx kurulumu
sudo apt update
sudo apt install -y nginx
# OAuth2 Proxy binary indirme (en güncel versiyonu GitHub'dan kontrol edin)
wget https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.6.0/oauth2-proxy-v7.6.0.linux-amd64.tar.gz
tar xzf oauth2-proxy-v7.6.0.linux-amd64.tar.gz
sudo mv oauth2-proxy-v7.6.0.linux-amd64/oauth2-proxy /usr/local/bin/
sudo chmod +x /usr/local/bin/oauth2-proxy
# Servis kullanıcısı oluşturma
sudo useradd --system --no-create-home --shell /bin/false oauth2proxy
Cookie şifreleme için güçlü bir secret üretmemiz gerekiyor:
# Cookie secret üretimi
python3 -c 'import os,base64; print(base64.urlsafe_b64encode(os.urandom(32)).decode())'
# Alternatif olarak openssl ile
openssl rand -base64 32
Bu komutu çalıştırarak aldığınız değeri not edin, birazdan kullanacağız.
Google OAuth2 Provider Yapılandırması
En yaygın kullanım senaryosu olan Google ile başlayalım. Önce Google Cloud Console’da uygulama oluşturmanız gerekiyor:
- Google Cloud Console’a gidin
- Yeni bir OAuth2 Client ID oluşturun (Web application türünde)
- Authorized redirect URIs kısmına
https://auth.yourdomain.com/oauth2/callbackekleyin - Client ID ve Client Secret’ı not alın
Şimdi OAuth2 Proxy konfigürasyon dosyasını oluşturalım:
sudo mkdir -p /etc/oauth2-proxy
sudo nano /etc/oauth2-proxy/config.cfg
# /etc/oauth2-proxy/config.cfg
# Provider ayarları
provider = "google"
client_id = "YOUR_GOOGLE_CLIENT_ID"
client_secret = "YOUR_GOOGLE_CLIENT_SECRET"
# Cookie ayarları
cookie_secret = "YOUR_BASE64_COOKIE_SECRET"
cookie_secure = true
cookie_httponly = true
cookie_samesite = "lax"
cookie_expire = "168h"
cookie_name = "_oauth2_proxy"
# Dinleme adresi
http_address = "127.0.0.1:4180"
# Email domain kısıtlaması (sadece şirket emaillerini kabul et)
email_domains = ["yourcompany.com"]
# Upstream (Nginx bu URL'yi kullanacak, biz burada "static://200" diyoruz)
# Nginx auth_request modunda çalışacağı için upstream yönetimini Nginx yapıyor
upstreams = ["static://200"]
# Redirect URL
redirect_url = "https://auth.yourdomain.com/oauth2/callback"
# Token yenileme
pass_access_token = true
pass_authorization_header = true
set_xauthrequest = true
# Logging
request_logging = true
Systemd Servis Tanımı
OAuth2 Proxy’yi sistem servisi olarak çalıştırmak, yeniden başlatmalarda otomatik olarak devreye girmesini sağlar:
sudo nano /etc/systemd/system/oauth2-proxy.service
[Unit]
Description=OAuth2 Proxy
After=network.target
[Service]
Type=simple
User=oauth2proxy
Group=oauth2proxy
ExecStart=/usr/local/bin/oauth2-proxy --config=/etc/oauth2-proxy/config.cfg
Restart=on-failure
RestartSec=5s
# Güvenlik ayarları
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/log/oauth2-proxy
# Environment
Environment=OAUTH2_PROXY_CLIENT_SECRET=YOUR_SECRET
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable oauth2-proxy
sudo systemctl start oauth2-proxy
sudo systemctl status oauth2-proxy
Nginx Yapılandırması: Temel auth_request Modülü
Nginx’in auth_request modülü, kimlik doğrulamayı subrequest olarak yönetmenizi sağlar. Ubuntu’daki Nginx paketlerinde bu modül varsayılan olarak derlenmiş gelir. Kontrol etmek için:
nginx -V 2>&1 | grep auth_request
# Çıktıda "--with-http_auth_request_module" görmek gerekiyor
Şimdi temel Nginx yapılandırmasını oluşturalım. Bu yapılandırmada, internal.yourdomain.com adresine gelen tüm istekleri OAuth2 ile koruyoruz:
# /etc/nginx/sites-available/internal-apps.conf
# OAuth2 Proxy için upstream tanımı
upstream oauth2_proxy {
server 127.0.0.1:4180;
keepalive 10;
}
# OAuth2 Proxy'nin kendisi için server bloğu
server {
listen 443 ssl http2;
server_name auth.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# SSL güvenlik ayarları
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
location /oauth2/ {
proxy_pass http://oauth2_proxy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $request_uri;
proxy_buffer_size 4k;
proxy_buffers 4 4k;
}
location = /oauth2/auth {
proxy_pass http://oauth2_proxy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
# Body göndermeye gerek yok
proxy_set_header Content-Length "";
proxy_pass_request_body off;
}
}
# Korunan uygulama: Grafana
server {
listen 443 ssl http2;
server_name grafana.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# Auth endpoint (internal, sadece auth_request kullanabilir)
location = /oauth2/auth {
internal;
proxy_pass http://oauth2_proxy;
proxy_set_header Host auth.yourdomain.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header Content-Length "";
proxy_pass_request_body off;
}
# OAuth2 callback ve static sayfalar
location /oauth2/ {
proxy_pass http://oauth2_proxy;
proxy_set_header Host auth.yourdomain.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $request_uri;
}
# Ana uygulama location bloğu
location / {
# Auth kontrolü
auth_request /oauth2/auth;
# Auth başarısız olunca ne yapılacağı
error_page 401 = /oauth2/sign_in;
# Auth'dan gelen header'ları backend'e geçir
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
auth_request_set $token $upstream_http_x_auth_request_access_token;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
proxy_set_header Authorization "Bearer $token";
# Backend proxy
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket desteği (Grafana için gerekli)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Keycloak ile OIDC Entegrasyonu
Kurumsal ortamlarda Keycloak gibi kendi barındırdığınız identity provider’lar çok daha yaygın. Keycloak için OAuth2 Proxy konfigürasyonu biraz farklı:
# /etc/oauth2-proxy/keycloak-config.cfg
provider = "oidc"
provider_display_name = "Şirket SSO"
# Keycloak OIDC endpoint'leri
oidc_issuer_url = "https://keycloak.yourdomain.com/realms/your-realm"
client_id = "nginx-oauth2-proxy"
client_secret = "YOUR_KEYCLOAK_CLIENT_SECRET"
# Redirect URL
redirect_url = "https://auth.yourdomain.com/oauth2/callback"
# Cookie ayarları
cookie_secret = "YOUR_BASE64_COOKIE_SECRET"
cookie_secure = true
cookie_domains = [".yourdomain.com"]
cookie_expire = "8h"
cookie_refresh = "1h"
# Dinleme
http_address = "127.0.0.1:4180"
# Upstream
upstreams = ["static://200"]
# OIDC scope'lar
scope = "openid profile email groups"
# Kullanıcı bilgileri
oidc_email_claim = "email"
oidc_groups_claim = "groups"
# Grup bazlı erişim kontrolü
# allowed_groups = ["/devops", "/developers"]
# Token geçiş ayarları
pass_access_token = true
pass_authorization_header = true
set_xauthrequest = true
set_authorization_header = true
# TLS doğrulama (internal CA için gerekebilir)
# ssl_insecure_skip_verify = true
Keycloak’ta client oluşturma adımları:
- Keycloak admin konsolunda ilgili realm’e gidin
- Clients menüsünden “Create client” seçin
- Client ID olarak
nginx-oauth2-proxygirin - Client authentication’ı “On” yapın
- Valid redirect URIs’e
https://auth.yourdomain.com/oauth2/callbackekleyin - Web Origins’e
https://auth.yourdomain.comekleyin
Çoklu Uygulama için Nginx Include Yapısı
Onlarca servisi koruyorsanız, her servis için tekrar tekrar auth_request blokları yazmak yerine include mekanizmasını kullanmak çok daha temiz:
# /etc/nginx/snippets/oauth2-auth.conf
location = /oauth2/auth {
internal;
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-Scheme $scheme;
proxy_set_header Content-Length "";
proxy_pass_request_body off;
proxy_cache_valid 200 1m;
}
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-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $request_uri;
}
# /etc/nginx/snippets/oauth2-params.conf
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
auth_request_set $token $upstream_http_x_auth_request_access_token;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
Artık herhangi bir servis bloğunda sadece şunu yazmak yeterli:
# /etc/nginx/sites-available/kibana.conf
server {
listen 443 ssl http2;
server_name kibana.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# Auth bloklarını include et
include snippets/oauth2-auth.conf;
location / {
# OAuth2 parametrelerini include et
include snippets/oauth2-params.conf;
proxy_pass http://127.0.0.1:5601;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Sık Karşılaşılan Sorunlar ve Çözümleri
Cookie domain sorunları: Birden fazla subdomain kullanıyorsanız cookie_domains = [".yourdomain.com"] şeklinde wildcard tanımlamanız gerekir. Aksi halde her subdomain için ayrı login gerekir.
Redirect loop: redirect_url ile Nginx’teki server_name uyuşmazsa sonsuz redirect döngüsüne girersiniz. OAuth2 Proxy loglarını inceleyin:
sudo journalctl -u oauth2-proxy -f
# veya
sudo journalctl -u oauth2-proxy --since "10 minutes ago"
Token refresh sorunları: Uzun süreli oturumlar için cookie_refresh değerini token_expire süresinden kısa tutun. Genellikle token ömrünün yarısı iyi bir değerdir.
Auth header encoding: Bazı backend uygulamalar Authorization header’ını bekler. pass_authorization_header = true ayarını yapın ve Nginx’te şunu ekleyin:
auth_request_set $auth_header $upstream_http_authorization;
proxy_set_header Authorization $auth_header;
Rate Limiting ve Güvenlik Sertleştirme
Auth endpoint’leri brute force saldırılarına karşı savunmasızdır. Nginx tarafında rate limiting eklemek önemli:
# nginx.conf - http bloğu içinde
limit_req_zone $binary_remote_addr zone=oauth2_limit:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/m;
# server bloğu içinde oauth2 location'larına ekle
location /oauth2/ {
limit_req zone=oauth2_limit burst=5 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:4180;
# ... diğer ayarlar
}
Güvenlik header’larını da eklemeyi unutmayın:
# Tüm korunan servislere eklenecek header'lar
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Monitoring ve Log Yapılandırması
Her şeyin düzgün çalıştığını izlemek için basit bir health check endpoint’i ekleyelim:
# Nginx'te health check location
location = /healthz {
access_log off;
return 200 "healthyn";
add_header Content-Type text/plain;
}
# OAuth2 Proxy health check
location = /oauth2/healthz {
proxy_pass http://127.0.0.1:4180/ping;
access_log off;
}
Log formatını zenginleştirerek kim ne zaman neye erişti bilgisine sahip olabilirsiniz:
log_format oauth2_combined '$remote_addr - $user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'email=$email';
# İlgili server bloğunda
access_log /var/log/nginx/internal-access.log oauth2_combined;
Gerçek Dünya Senaryosu: DevOps Araçları Stack’i
Tipik bir DevOps ortamında şu araçları tek kimlik doğrulama altında toplamak mümkün:
- Grafana (port 3000): Metrik ve dashboard görselleştirme
- Kibana (port 5601): Log analizi
- Prometheus (port 9090): Metrik toplama
- Alertmanager (port 9093): Alert yönetimi
- ArgoCD (port 8080): GitOps deployment
Bu araçların hepsi için tek bir Keycloak realm üzerinde grup bazlı erişim tanımlarsınız: devops-team grubu hepsine erişebilir, developers grubu sadece Grafana ve Kibana’ya, ops-readonly grubu ise sadece read-only dashboardlara erişebilir.
OAuth2 Proxy’nin allowed_groups konfigürasyonu servis bazında değiştirilmek istenirse, her servis için ayrı bir OAuth2 Proxy instance çalıştırabilir, farklı portlarda (4180, 4181, 4182…) dinleyip farklı grup kısıtlamaları uygulayabilirsiniz.
Sonuç
Nginx ile OAuth2 Proxy entegrasyonu, dağınık authentication yönetimini merkezi bir yapıya dönüştürmenin en pratik yollarından biri. Özellikle internal araçlar ve mikroservis mimarilerinde, her servise auth kodu yazmak yerine altyapı katmanında bu problemi çözmek hem güvenliği hem de geliştirici deneyimini önemli ölçüde iyileştirir.
Kurulumda dikkat edilmesi gereken birkaç kritik nokta var: cookie secret’ların güçlü ve rastgele olması, HTTPS’in mutlaka kullanılması, redirect URL’lerin doğru yapılandırılması ve log monitoring’in ihmal edilmemesi. Keycloak gibi kurumsal bir identity provider kullandığınızda grup bazlı erişim kontrolü de devreye girerek RBAC modelini altyapı seviyesine taşıma imkanı doğuyor.
Bir sonraki adım olarak bu yapıya JWT doğrulama eklemek, API gateway senaryolarında token introspection uygulamak veya multi-tenant yapılarda tenant izolasyonunu Nginx map direktifi ile yönetmek ele alınabilir. Ancak bu yazıda anlattığımız temel kurulum, büyük çoğunluğu için sağlam ve yönetilebilir bir başlangıç noktası sağlayacaktır.
