GitHub Desktop'ta Çalışan Git, Terminalde Neden "Authentication failed" Diyor?
Şirket içi Azure DevOps Server'da PAT ile Basic kimlik doğrulama
Bu sayfa şu dilde de var: English
İçindekiler
Bir mobil projede yeni bir branch açmam gerekiyordu. Sıradan bir iş: git fetch, git branch, devam. Ama ilk komut şunu verdi:
| |
Aynı sunucudaki başka bir repoda da aynı hata vardı. Üstelik GitHub Desktop aynı sunucuya sorunsuz bağlanıyordu. Bu yazı, çözüme giden yolu, yolda yaptığım yanlış teşhisleri ve sonunda sorunu çözen tek satırlık ayarı anlatıyor.
Eğer şirket içinde kurulu bir Azure DevOps Server (eski adıyla TFS) kullanıyor ve terminalde bu hatayı alıyorsanız, çözüm büyük ihtimalle sonda.
Ortam
- Windows 11, Git for Windows 2.52
- Şirket içi Azure DevOps Server (on-prem), alan adı (domain) hesaplarıyla giriş
- Git Credential Manager (GCM) 2.6.1, yani
credential.helper = manager - Kimlik doğrulama için Personal Access Token (PAT)
İlk bulgu: sunucu ayakta, kimlik reddediliyor
Önce ağ sorununu eledim. Sunucuya basit bir istek attım:
| |
İki şey öğrendim:
- VPN/ağ sorunu değil. Sunucu yanıt veriyor.
- Sunucu dört kimlik doğrulama yöntemi sunuyor:
Bearer,Basic,NegotiateveNTLM. Bu satırı aklınızda tutun, hikâyenin anahtarı bu.
Yanlış teşhis #1: “Ekipte değilsin”
Projenin ekibinde adımın olmadığını fark edip kendimi hem üye hem yönetici olarak ekledim. Mantıklı görünüyordu ama hata aynen devam etti.
Dersi sonradan anladım: Azure DevOps’ta 401 “kimliğin doğrulanamadı” demektir. Yetki sorunu olsaydı 403 ya da TF401019 gibi bir mesaj görürdüm. Üstelik ekip üyeliği, repo erişimini kendiliğinden vermez, o ayrı bir güvenlik ayarıdır.
PAT’in kendisinin geçerli ve yetkili olduğunu REST API ile ayrıca doğruladım:
| |
Yani repo okunabiliyordu. Sorun yetkide değildi.
Yanlış teşhis #2: “Eski kaydı sil”
Windows Credential Manager’da GitHub - https://azuredevops.sirket.local/... adlı bir kayıt gördüm ve bayatlamış olduğunu varsaydım. Sildim, GitHub Desktop’ta fetch yapınca giriş sordu, bilgileri girdim ve çalıştı. Ama terminalde hâlâ aynı hata vardı.
Burada ikinci dersi aldım: GitHub Desktop ve terminaldeki Git aynı sunucuyla konuşuyor ama kimlik bilgisini ayrı yerlerde saklıyor.
| Kimlik kaydı adı | Kullanan | |
|---|---|---|
| GitHub Desktop | GitHub - https://sunucu/... | Kendi Git’i ve kendi kimlik yönetimi |
| Terminaldeki Git | git:https://sunucu | Git Credential Manager (GCM) |
Sildiğim kayıt aslında GitHub Desktop’ındı. Terminal Git hiç onu kullanmıyordu. Silmek terminali etkilemediği gibi, Desktop’ın kendi kaydını da gereksiz yere bozmuştu.
İpucu: GCM izini açmak
GCM bir iz (trace) üretebiliyor:
| |
Çıktının önemli kısmı şuydu:
| |
Bu izden iki şey anlaşılıyor:
- GCM kayıtlı bir kimlik bulamıyor.
- Sunucu Windows Integrated Authentication (Windows hesabıyla otomatik giriş) desteklediği için GCM boş bir kullanıcı adı/şifre üretip Git’e veriyor ve bana hiçbir şey sormuyor. Bu otomatik giriş benim makinemde (alan adına bağlı değil) başarısız oluyor ve hata veriyor.
Düzeltme 1: Windows otomatik girişini kapatmak
| |
Bu işe yaradı, ama yalnızca yarım: artık GCM bir pencere açıp kullanıcı adı ve şifre soruyordu. Girdim ve… yine Authentication failed.
Kimlik bilgisi doğru mu? Git’ten bağımsız test
Aynı kullanıcı adı ve PAT’in gerçekten geçerli olup olmadığını Git’i devre dışı bırakıp curl ile sınadım:
| |
Şifre sorusuna PAT’i yazdım. Sonuç: http=200.
Kimlik bilgisi doğruydu. Aynı bilgiyle curl çalışıyor, git çalışmıyordu. Demek ki sorun Git’in HTTP istemcisinin davranışındaydı, kimlikte değil. Ayrıca GCM’i tamamen devre dışı bırakıp (-c credential.helper=) Git’in kendisine sordurduğumda da aynı hata geldi, yani GCM de suçlu değildi. SSL arka ucunu openssl‘e çevirmek de bir şey değiştirmedi.
Bu arada istemde dikkatimi çeken bir şey vardı:
| |
\ karakteri %5C olarak görünüyordu ve “belki sorun bu” diye düşündüm. Değildi. Bu yalnızca Git’in kullanıcı adını URL biçiminde göstermesi. Sunucuya çözülmüş hâliyle giden değer ALANADI\kullanici.
Asıl neden: Git en “güçlü” yöntemi seçiyor
curl -u doğrudan Basic kimlik doğrulama gönderiyor. Git ise farklı çalışıyor: önce kimlik bilgisi olmadan istek atıyor, sunucunun 401 yanıtındaki yöntem listesine bakıyor ve libcurl’ün varsayılan davranışıyla en güçlü gördüğü yöntemi seçiyor. Listede Negotiate ve NTLM olduğu için Basic yerine bunlardan biri seçiliyor. PAT bir NTLM şifresi olmadığı için sunucu reddediyor.
Başta gördüğüm dört satırlık WWW-Authenticate listesi tam olarak buydu.
Çözüm: Basic’i baştan göndermeye zorlamak
Git 2.46 ile gelen http.proactiveAuth ayarı, ilk istekte yöntem pazarlığı yapmadan doğrudan belirtilen kimlik doğrulamayı göndermeyi sağlıyor:
| |
Kullanıcı adı ve PAT’i girdim. Bu sefer fatal yoktu, komut sessizce bitti. Çalışmıştı.
Kalıcı yapmak için, yalnızca ilgili sunucuya özel olarak:
| |
İkinci komutta GCM penceresi bir kez açılıp kullanıcı adı ve PAT’i sordu, kaydetti. Sonrasında aynı sunucudaki diğer repolarda da tekrar sormadan çalıştı.
Özet: tek başına yeterli olan ayarlar
Benim durumumda gereken iki ayar buydu. Sorunu asıl çözen proactiveAuth oldu:
| |
allowWindowsAuth false, GCM’in boş (WIA) kimlik üretip hiçbir şey sormamasını engelliyor. proactiveAuth basic ise Git’in Basic yerine Negotiate/NTLM’e takılmasını önlüyor. Kurulumunuzda allowWindowsAuth ayarına ihtiyaç olmayabilir, ama iz çıktısında “Host supports WIA” görüyorsanız ikisini birlikte ayarlamak güvenli.
Çıkardığım dersler
- 401 ile 403 aynı şey değil. 401 kimlik doğrulama, 403 yetki sorunudur. Ekibe kendimi eklemek gereksiz bir yan yoldu.
- Hatanın hangi katmanda olduğunu ayırın.
curl(200) ilegit(hata) arasındaki fark, sorunu “kimlik bilgisi” katmanından “Git’in HTTP davranışı” katmanına taşıdı. Bu tek karşılaştırma yüzlerce tahminden değerliydi. - GitHub Desktop çalışıyor diye terminal çalışacak demek değil. İkisi kimlik bilgilerini ayrı yerlerde saklıyor ve farklı Git ikilileri kullanabiliyor. Bir kaydı silmeden önce hangi aracın kaydı olduğundan emin olun.
- İz (trace) açın.
GCM_TRACE=1ile “boş kimlik üretildi” satırını görmek, GCM’in neden hiçbir şey sormadığını açıkladı. - Sunucunun
WWW-Authenticatelistesine bakın. Aynı andaBasicveNegotiate/NTLMsunan on-prem sunucularda PAT ile Git kullanıyorsanız bu hatayı tekrar görebilirsiniz.
Hızlı kontrol listesi
Aynı hatayı alıyorsanız sırayla:
curl -I <repo-url>ile 401 veWWW-Authenticatebaşlıklarını görün.curl.exe -u "ALANADI\kullanici" <repo-url>/info/refs?service=git-upload-packile kimlik bilgisini Git’ten bağımsız doğrulayın.200bekliyoruz.GCM_TRACE=1 git fetchile GCM’in ne yaptığına bakın. “generating empty credential” görüyorsanızallowWindowsAuth falseekleyin.- Hâlâ başarısızsa
git -c credential.helper= -c http.proactiveAuth=basic fetchdeneyin. - Çalışırsa
proactiveAuth basicayarını ilgili sunucuya özel kalıcı yapın.
Umarım bir sonraki sefer bu hatayla uğraşan biri bu yazı sayesinde saatler kazanır.
Not
Yazıdaki sunucu ve alan adları anonimleştirilmiştir. PAT’i hiçbir zaman komut satırına veya URL’ye açık yazmayın, etkileşimli giriş ya da kimlik yöneticisi kullanın.
Son güncelleme: