CLI kimlik doğrulaması, doğru yöntem
(abgeo.dev)- Birçok CLI, dizüstü bilgisayardaki yerel tarayıcıda hızlıca tamamlanan localhost OAuth yönlendirmesini varsayılan olarak kullanır; ancak SSH, konteyner ve WSL gibi geliştirme ortamlarında bu varsayım bozulur ve giriş akışı durur
- Mevcut yöntemde CLI,
127.0.0.1üzerinde geçici bir HTTP sunucusu açar, tarayıcıyı kimlik doğrulama URL’sine gönderir ve ardından kimlik sağlayıcı authorization code’u yerel callback’e geri döndürür - 2019’da standartlaştırılan RFC 8628 Device Authorization Grant, token isteyen CLI ile kullanıcının kimlik doğruladığı tarayıcı cihazını ayırarak port bind etme ve yerel tarayıcı bağımlılığını ortadan kaldırır
- Device flow,
device_code,user_code,verification_uri,intervalalır ve/tokenuç noktasını periyodik olarak poll eder;authorization_pending,slow_down,access_denied,expired_tokengibi standart durumları işler - Yeni bir CLI geliştiriliyorsa varsayılan olarak device flow kullanılmalı, uç noktalar
.well-known/openid-configurationile keşfedilmeli ve refresh token~/.configaltındaki bir JSON dosyasında değil, OS keychain içinde saklanmalıdır
localhost yönlendirmesinin varsaydıkları
- Yaygın CLI giriş yöntemi, yerel HTTP sunucusunun ve sistem tarayıcısının aynı makinede olduğu varsayımıyla çalışır
- CLI,
127.0.0.1üzerindeki belirli bir porta HTTP sunucusu bind eder - Sistem tarayıcısını OAuth authorization endpoint’ine açar ve
redirect_uri=http://127.0.0.1:<port>/callbackekler - Kullanıcı giriş yaptığında kimlik sağlayıcı authorization code’u loopback URL’ye
302ile yönlendirir - CLI içindeki küçük HTTP sunucusu code’u okuyup token endpoint’te token ile değiştirir
- Çoğu durumda PKCE eklenir ve ardından “bu sekmeyi kapatabilirsiniz” sayfası gösterilir
- CLI,
gcloud auth login,wrangler login, eskivercel loginve çeşitli üretici CLI’ları bu yöntemi kullanır- Wrangler
8976portunu kullanır - gcloud
8085kullanır - Claude Code her çalıştırmada geçici bir port seçer
- Wrangler
- RFC 8252, yerel uygulamalarda tarayıcı mevcutsa bu deseni önerir, ancak ana makinede tarayıcı olmadığında ne yapılacağını ele almaz
Kullanıcıların localhost adımını çoğu zaman fark etmemesinin nedeni
- localhost callback çok kısa sürdüğü için kullanıcıların çoğu bunu görmez
- CLI’nin yazdırdığı URL uzundur ve redirect URI bunun query string’i içinde yer alır
- Kullanıcılar giriş ve onayı kimlik sağlayıcının gerçek alan adında yapar
- Kimlik sağlayıcı daha sonra tarayıcıyı localhost callback’e gönderir, CLI code’u okur ve ardından daha cilalı bir “signed in” sayfasına geçilir
- Dışarıdan bakınca “web sitesinde giriş yaptım, CLI de doğrulandı” gibi görünür; ama gerçekte akışı ayakta tutan şey yerel HTTP sunucusu ile tarayıcının birlikte var olmasıdır
SSH, konteyner ve WSL’de kırılan nokta
- Tüm akış, CLI’nin çalıştığı makine ile tarayıcının çalıştığı makinenin aynı olduğu varsayımına dayanır
- SSH oturumunda uzak ana makinede tarayıcı yoktur;
xdg-openbaşarısız olabilir ya da X forwarding ortamında görünmeyen bir uzak tarayıcı açılabilir- Callback portu dizüstüne tünellenebilir, ancak kimlik sağlayıcıya kayıtlı redirect URI’nin tünelden geçen bu porta izin vermesi gerekir
- Konteynerlerde tarayıcı yoktur ve birçok imajda
xdg-openveyaopenda bulunmaz- Callback portu
-pile açığa çıkarılabilir, fakat bunun için CLI’nin hangi portu kullanacağını bilmek gerekir - Cloudflare CLI’da bu nedenle engellenen kullanıcıların issue kayıtları birikmiştir
- Callback portu
- WSL’de tarayıcı Windows üzerinde açılırken loopback sunucusu Linux üzerinde çalışır
- WSL2’nin port yönlendirmesi çoğu zaman işe yarasa da her zaman güvenilir değildir
- Paylaşılan makinelerde aynı makinedeki başka süreçler
/proc/net/tcpüzerinden dinlenen portu bulabilir veya bilinen portu önce bind etmek için yarışabilir- PKCE, code exchange’i korur; fakat redirect’in kendisindeki authenticated session’ı korumaz
fallback’in varlığı bile tasarım sorununu gösteriyor
- Loopback akışını varsayılan sunan CLI’lar, bozulma ihtimaline karşı fallback de sağlar
- gcloud’da
--no-launch-browserseçeneği vardır - Wrangler takılır ve kabul görmüş geçici çözüm, ikinci bir terminalde localhost URL’sine doğrudan curl atmaktır
- Anthropic’in
claudearacı “Paste code here if prompted” çıktısını verip bekler - Bu fallback’ler fiilen manuel bir device flow anlamına gelir; yani CLI’nin gerçekte kullanıldığı ortamlarda varsayılan akış çalışmadığı için vardır
RFC 8628 Device Authorization Grant
- RFC 8628, 2019’da “input-constrained devices” için yayımlanan OAuth 2.0 Device Authorization Grant standardıdır
- TV’ler, konsollar ve CLI’lar hedef kullanım alanları arasındadır
- Temel fikir, token isteyen cihaz ile kullanıcının kimlik doğruladığı cihazı birbirinden ayırmaktır
- CLI, kimlik sağlayıcının
device_authorization_endpointuç noktasına POST isteği gönderir- Örnek istekte
client_id=my-cli&scope=openid+offline_accessgönderilir
- Örnek istekte
- Kimlik sağlayıcı aşağıdaki değerleri içeren bir JSON döndürür
device_codeuser_codeverification_uriverification_uri_completeexpires_ininterval
- CLI URL’yi ve kısa kodu ekrana yazdırır; mümkünse
verification_uri_completeiçin QR da gösterir - Kullanıcı istediği cihazda URL’yi açar, giriş yapar, istenen scope ve client name’i görür, ardından bunun CLI’de gösterilen kısa kodla eşleştiğini doğrulayıp onay verir
Polling ve standart durum işleme
- CLI, token endpoint’i
intervalsaniyede bir poll eder - Grant type olarak
urn:ietf:params:oauth:grant-type:device_codekullanılır - RFC 8628 section 3.5 şu durumları tanımlar
authorization_pending: kullanıcının onayı bekleniyorslow_down: kimlik sağlayıcı polling aralığının düşürülmesini istiyor; şartname interval’in en az 5 saniye artırılmasını söyleraccess_denied: kullanıcı isteği reddettiexpired_token: çok uzun beklendiği için token süresi doldu
- Device flow’da CLI bir porta bind etmez ve çalıştığı ana makinede tarayıcı bulunduğunu varsaymaz
- Aynı giriş yöntemi dizüstünde, konteynerde ve insan onayı bekleyen bir CI job içinde çalışabilir
Polling maliyeti ve uç nokta keşfi
- Varsayılan polling aralığı 5 saniyedir
- Kimlik doğrulamaların çoğu 1 dakika içinde tamamlandığı için tipik bir girişte
/tokenuç noktasına yaklaşık 10 kez poll yapılıp durulur - Sunucu
slow_downile aralığı artırabilir ve düzgün yazılmış istemcilerin buna uyması gerekir - Her bekleyen giriş için stateful bir endpoint’e WebSocket veya SSE bağlantısı açık tutmakla karşılaştırıldığında,
/tokenüzerinde stateless polling daha basit ve daha ucuzdur - Kimlik sağlayıcı OpenID Connect Discovery destekliyorsa CLI,
.well-known/openid-configurationüzerindendevice_authorization_endpointvetoken_endpointbilgilerini alarak URL’leri sabit kodlamaktan kaçınabilir
device flow’un phishing riski
- Device flow’da saldırgan, gerçek kimlik sağlayıcının
device_authorization_endpointuç noktasını çağırıpuser_codevedevice_codealdıktan sonra kurbanı bu kodu girmeye ikna eden bir saldırı düzenleyebilir - Kurban gerçek URL’de, gerçek kodla giriş yapıp gerçek consent screen’i onaylayabilir
- Saldırgan ise kendi oluşturduğu
device_codeile/tokenuç noktasını poll ederek access token’ı alır - Rus tehdit aktörleri Ağustos 2024’ten beri M365 tenant’larını hedefleyen bu kampanyayı yürütüyor
- Microsoft Threat Intelligence bunu Storm-2372 olarak izliyor
- Volexity, bunu APT29/Midnight Blizzard olarak ilişkilendiriyor
- Kamu, savunma ve STK tenant’ları birden fazla kıtada etkilendi
phishing savunması kimlik sağlayıcının sorumluluğunda
- Phishing savunması CLI tarafında değil, kimlik sağlayıcı tarafında yapılmalıdır
- Gerekli azaltım önlemleri şunlardır
- kısa
user_codeson kullanma süresi - verification page üzerinde client name ve istek kaynağının belirgin şekilde gösterilmesi
- code girme denemelerine rate limiting uygulanması
- kurbanın bağlantıya tıklaması yerine kodu elle girmesini teşvik etmek için
verification_uri_completedeğerinin gösterilmemesi - yüksek değerli tenant’larda, bilinen ağ veya cihaz değilse device code flow’un conditional access policy ile engellenmesi
- kısa
- CLI’nin görevi şartnameye uymak ve kestirme yollar oluşturmamaktır
- Device flow, yerel attack surface’i sosyal attack surface’e dönüştürür; ancak daha fazla ortamda çalışan bir akış sunmak ve kimlik sağlayıcının mitigation’larından yararlanmak daha doğru yaklaşımdır
Go uygulama örneğinde temel akış
- Tüm uygulama Go’da yalnızca
net/httpkullanılarak yaklaşık 30 satıra sığar - Uygulama akışı şöyledir
client_idvescopeileDeviceAuthorizationEndpointiçinhttp.PostFormçağrısı yapılır- Yanıt JSON’undan
DeviceCode,UserCode,VerificationURIComplete,Intervalalanları decode edilir - Kullanıcıya
VerificationURICompleteveUserCodeyazdırılır TokenEndpointiçindevice_code,client_idve device grant type içeren tekrar eden POST istekleri gönderilirauthorization_pendingise beklemeye devam edilirslow_downise interval 5 saniye artırılır- Hata yoksa
access_tokenverefresh_tokendöndürülür - Diğer hatalar başarısızlık olarak işlenir
- Keycloak realm’inde “OAuth 2.0 Device Authorization Grant” yeteneği açılırsa veya bu grant’i destekleyen OpenID sertifikalı bir sağlayıcı kullanılırsa device-flow login çalışır
Yeni CLI’lar için varsayılan olması gereken yöntem
- Varsayılan olarak device flow kullanılmalıdır
- Uç noktalar
.well-known/openid-configurationile keşfedilmeli, URL’ler sabit kodlanmamalıdır intervalveslow_downkurallarına mutlaka uyulmalıdır- Refresh token,
~/.configaltındaki JSON dosyasında değil OS keychain içinde saklanmalıdır - Hızlı dizüstü girişleri için loopback yolu sunulmak isteniyorsa bu,
--webbayrağının arkasında olmalı; varsayılan olmamalıdır
Zaten geçiş yapan CLI’lar ve geride kalan araçlar
- Device flow’u varsayılan kullanan CLI’lar var
gh auth login, baştan beri device flow kullanıyor ve açık kaynak dünyasında en temiz referans uygulamalardan biri sayılıyoraws sso login, IAM Identity Center için device flow’u uçtan uca çalıştırıyorvercel login, Eylül 2025’te RFC 8628’e geçti ve e-posta tabanlı girişiyle önceki--oobbayrağının yerini aldı- Stripe CLI, doğrudan RFC 8628 kullanmasa da kullanıcı deneyimi iyi tasarlanmış bir pairing-code flow uyguluyor
- Hâlâ loopback flow’u varsayılan tutup üstüne paste-the-code fallback ekleyen araçlar da var
- Google
gcloud - Cloudflare
wrangler - Anthropic
claude
- Google
- CLI, dizüstü dışındaki her ortamda manuel paste-the-code fallback gerektiriyorsa, o fallback’i doğrudan varsayılan akış olarak sunmak daha mantıklıdır
1 yorum
Lobste.rs görüşleri
İfade biraz özensiz ama ilginç. Cihaz kodu/bağlantısı 1 dakikada bir değiştirilirse, phishing için kötüye kullanılma ihtimali de azalabilir gibi görünüyor
Bir kez kullanıldıktan sonra rotasyonu durdurup ilgili oturumu IP veya tarayıcıya bağlamak yeterli olur
Microsoft gibi kullanıcının kodu elle girdiği sağlayıcılarda, landing page bir yönerge gösterip kodu panoya kopyalayarak phishing’e düşmeyi daha da kolaylaştırabilir
Güzel bir yazı; herkesin RFC 8628 tarafına geçmesi gerektiğine katılıyorum
Uzak geliştirme makinesinde CLI OAuth sürecini fazla sık yaşadığım için,
xdg-opençağrılarını yakalayıp portları otomatik forward ederek kötü kullanıcı deneyimini gizleyen kişisel bir araç yazdım: https://github.com/phinze/bankshotİlginç. Kısa süre önce tam da “eski” kimlik doğrulama yöntemi olan RFC 8252’yi uyguladım ama “yeni” yöntem olan RFC 8268’i bilmiyordum
Ana kullanım senaryom Google sunucu kimlik doğrulaması olduğu için burada bir bilgi boşluğu oluşmuş gibi görünüyor. RFC 8268 akışı sandığım belgede şöyle açıkça yazıyor
Google’ın scope kısıtlaması, OIDC’nin karmaşık şekilde ortaya çıktığı nokta. İdeal olarak Google’ın erişim token’ına tıkıştırması yerine bir ID token döndürmesi gerekir, ama bu Google’ın OAuth yapılandırma meselesi; 8628’in kendine özgü bir özelliği değil
OAuth’nun bitmeyen karmaşıklığı buradan geliyor. Standart, yetkilendirme yapısını nasıl kurulup taşınacağı konusunda çerçeveyi iyi tanımlıyor, ama bunun neyi temsil etmesi gerektiği konusunda bilinçli olarak sessiz kalıyor. “Çoğu” sağlayıcının uzlaştığı ortak HTTP endpoint kümesini elde etmek için bile OIDC’nin icadı ve yıllar gerekmişti
Bir başka hack de sunucudaki xdg-open çağrısını dizüstüne forward etmek. Kişisel altyapım için bunu yapan küçük bir araç yazdım: https://github.com/zimbatm/subportal/
Bu iki yaklaşım birleştirilemez mi?
localhostURL’sine redirect ediphellogeri döndürmesini sağlarsın; istemcihelloalamazsa CLI’de URL’yi yazdırırsınAynı anda, sunucunun gönderdiği
helloya yanıt gelmezse tarayıcıda bir kod gösterip “giriş yapmaya çalışanın siz olduğunu doğrulayın” gibi bir mesaj gösterebilirsin. Google’daki gibi telefonda seçilecek sayılar göstererek bunu daha da kolaylaştırmak mümkünBunun avantajı, 2. durumda bile insanların bağlantıya tıklamayı kolay bulmasına rağmen OTP/kod paylaşımını nispeten daha az yapması ve saldırganın saldırı sırasında sosyal mühendislikle sürekli devrede kalmak zorunda olması
Yerel makinede düzgün çalıştığında etkileşim gerekmiyor; bu yüzden varsayılanın tarayıcı tabanlı akış olmasını isterdim