Merhaba,
Dün akşam saatlerine bir yazılımcı, linkedin üzerinden mikroservis mimarisi ile geliştirdiği bir projede karşılaştığı problemi çözmek için benimle iletişime geçti. Kısa bir görüşme ile birlikte hatayı ekran üzerinden inceledik ve problemi kaynağında çözerek sistemin doğru şekilde çalışmasını sağladık.
Bu yazımda, yaşanan bu problemi ve çözümünü paylaşmak istiyorum. Mikroservis tabanlı sistemlerde Ocelot ve IdentityServer birlikte kullanıldığında benzer hataların yaşanması oldukça yaygın. Özellikle authentication tarafındaki küçük bir yanlış yapılandırma bile sistemin çalışmamasına sebep olabiliyor.
🧩 Problem: Doğru İstek, Yanlış Token Handler
Senaryo şu şekildeydi:
-
Ocelot API Gateway kullanılıyor.
-
IdentityServer ile authentication sağlanıyor.
-
Mikroservislerden biri kullanıcıya özel veriler döndürüyor.
-
Gateway üzerinden yapılan isteklerde token alınabiliyor ama hedef servis tarafında
User.Identity.Nameya dasub(subject) gibi kullanıcı bilgileri gelmiyordu.
İlk başta token doğru alınmasına rağmen, mikroservis tarafında kullanıcıya özel bilgi alınamaması kafa karıştırıcıydı. Ancak Program.cs dosyasındaki bir satır bu problemi açıklıyordu:
services.AddHttpClient<IExampleService, ExampleService>(opts =>
{
opts.BaseAddress = new Uri("https://gateway-url/api/example");
}).AddHttpMessageHandler<ClientCredentialTokenHandler>();
✅ Çözüm: Doğru Handler ile Kullanıcı Bilgisini Almak
Kullanıcıya özel veri veya kullanıcı bilgisine ihtiyaç vardı. Bu sebeple ClientCredentialTokenHandler yerine ResourceOwnerPasswordTokenHandler kullanılmalıydı:
services.AddHttpClient<IExampleService, ExampleService>(opts =>
{
opts.BaseAddress = new Uri("https://gateway-url/api/example");
}).AddHttpMessageHandler<ResourceOwnerPasswordTokenHandler>();
Bu değişiklikten sonra alınan access token, kullanıcının sub bilgisini taşıyordu. Mikroservislerde yapılan [Authorize] kontrolleri ve HttpContext.User üzerinden gelen bilgiler doğru şekilde çalışmaya başladı.
📚 Bilgi - Grant Type ve Handler Farkı
-
ClientCredentials Grant Type
→ Arka plan servisleri için uygundur. Kullanıcı bilgisi taşımaz.
→ Örn: sistem içi servislerin birbirine erişmesi. -
ResourceOwnerPassword Grant Type
→ Kullanıcı adı ve şifre ile token alınır. Kullanıcı bilgisi (
sub,name,role) token içinde yer alır.
→ Örn: kullanıcıya özel veri döndüren servisler.
Bu senaryoda handler’ların karışması, doğru token alınmasına rağmen sistemin beklenen şekilde davranmamasına sebep oldu.
|
Grant Type
|
Kullanıcı Bağlamı
|
Ne Zaman Kullanılır?
|
|---|---|---|
|
Client Credentials
|
❌ Yok
|
Arka plan servisleri, sistemler arası işlem
|
|
Resource Owner Password
|
✅ Var
|
Kullanıcı login olur, kimlik bilgisi gerekir
|
🗨️ Kapanış
Bu yaşanan senaryo bana bir kez daha gösterdi ki; bazen sadece birkaç satırlık konfigürasyon, tüm sistemi ciddi şekilde etkileyebiliyor. Özellikle mikroservis mimarisinde token yönetimi, authentication ve authorization gibi konular yüzeysel geçilemeyecek kadar derin. Küçük bir yapılandırma farkı bile tüm güvenlik altyapısının işleyişini değiştirebilir. Bu yüzden sistemin mimarisini iyi anlamak, her parçanın neden var olduğunu bilmek ve yapılandırmaları bilinçli şekilde yapmak yazılım dünyasında olmazsa olmazlardan biri.
Görüşmek üzere! 👋