Keycloak | Asp.NET Core İle Direct Grant Flow Authentication #8
Merhaba,
Bu içeriğimizde kullanıcıyı login ekranına hiç yönlendirmeksizin, uygulama aracılığıyla username + password’ü doğrudan Keycloak’a gönderip access token alınmasını sağlayacak olan Direct Grant Flow davranışını mercek altına alıyor olacağız.
Direct Grant Flow Nasıl Bir Davranışa Sahiptir?
Direct Grant Flow’da browser yoktur, redirect yoktur, HTML form yoktur… Tamamen arka planda programatik olarak çalışan bir kimlik doğrulama şeklidir…
Direct Grant Flow’da uygulama Keycloak’a arka plandan programatik olarak username & password bilgilerini gönderir, Keycloak ise bu bilgileri doğrulayarak token üretir. Böylece kullanıcıyı Keycloak’a yönlendirmeksizin sıfır etkileşimle token alınmasını sağlar. Bu işlem, OAuth2 Resource Owner Password Credentials Grant‘in Keycloak tarafındaki karşılığıdır.
Hangi Durumlar/Senaryolar İçin Tasarlanmıştır?
Direct grant flow, özellikle backend ağırlıklı çalışmalar için oldukça kullanışlıdır. Misal olarak; eski CLI araçları, script’ler, cron job’lar da bir login olma ihtiyacı varsa süreci daha da komplike etmemek için bu akıştan istifade edilebilir ve kullanıcı adı ve şifre odaklı çalışma hızlıca sağlanarak gerekli yetkilendirme gerçekleştirilebilir. Ayrıca tarayıcının kullanılamayacağı mobil veya desktop uygulamalarda login olunması gerekiyorsa eğer yine bu akıştan istifade edilebilir yahut müdahale ihtimali düşük olan legacy sistemlerde de login ihtiyacını giderebilmek için de tercih edilebilir. Tabi bu ve bunlara benzer durumları saymakla bitiremesek de kısaca aşağıdaki gibi özetleyebilir ve genel bir tanımda bulunabiliriz…
| Durum | Nedeni? |
Öneriliyor mu?
Alternatifi var mı?
|
|---|---|---|
| Eski CLI araçları, script’ler, cron job’lar | Çünkü bu tarz eski sistemlerde token almak için yapılacak çalışmalar aşırı derecede dallanıp budaklanabilir ve zaten muhtemelen karmaşık olan yapı daha da arap saçına dönerek geliştiricileri zorlayabilir. O yüzden kullanıcı adı ve şifre ile token almak en basit ve ideal çözüm olacaktır. |
✔
✖
|
| Kurumsal iç ağda, güvenilir mobil/desktop uygulamalar | Kurumsal iç ağlarda genellikle uygulamalar geliştiricilerin kontrolünde olurlar ve credentials’ın çalışmayacağına dair bir güven söz konusu olur. |
✔
✖
|
| Legacy sistem entegrasyonu | Eski sistemler genellikle başka bir akış bilmezler ya da farklı bir akışa yüksek direnç gösterebilirler. |
✔
✖
|
| Testing / development ortamları | Bu ortamlarda amaç genellikle business logic kontrolünü sağlamak olduğundan login süreçlerindeki akış maliyetlerinden kaçınmak için kullanılabilir. |
✔
İstenirse bu ortamlarda da geliştirme sağlanabilir, ancak gereksiz ve yersiz bir maliyet yaratacağı için önerilmez!
|
| Özel uygulama login ekranları | Kimi uygulamalarda login ekranları uygulamaya özel olarak tasarlanmakta ve Keycloak’ın login UI’ı hiç kullanılmamaktadır. Böyle durumlarda bu akış oldukça etkili çözüm sağlıyor olacaktır. |
✔
✖
|
| Microservice / sistemden sisteme kullanıcı doğrulama | Bir servis browser akışı olmaksızın kullanıcı adına işlem yapacaksa eğer tercih edilebilir. |
Pek değil!
Client Credentials Flow
|
Peki hangi durumlarda tercih edilmemelidir?
Direct grant flow, özellikle public olan yazılımlarda tercih edilmemelidir. Misal olarak; 3. taraf mobil uygulamalarda bu flow’u kullanmak credentials’ın uygulama içinde saklanmasından dolayı çok tehlikelidir.
Ayrıca modern SPA + backend uygulamalarda Authorization Code Flow + PKCE ve machine-to-machine çalışmalarında ise Client Credentials Flow yaklaşımları çok daha güvenli olacağından dolayı bu tarz senaryolarda da önerilmemektedir.
IoT cihazları sorarsanız eğer bu tarz durumlarda da cihaz akışları söz konusu olacağından Device Authorization Grant tercih edilmelidir.
Yani anlayacağınız browser tabanlı web uygulamalarında, SSO beklentisi olan sistemlerde, MFA / OTP gibi gelişmiş auth gerektiren senaryolarda ve güvenliği öncelik olan modern uygulamalarda direct grant flow kullanılmamalıdır!
Direct Grant Flow’da, kimlik avı (phishing) ve kimlik bilgilerinin sızdırılması (credential leakage) riski her daim söz konusudur! O yüzden dikkatli kullanılmalıdır.
Direct Grant Flow’un İç Yapısı
Direct grant flow’un iç yapısı aşağıdaki gibidir.
├── Username Validation (execution)
├── Password (execution)
├── Direct Grant – Conditional OTP (sub-flow)
│ ├── Condition – user configured (condition)
│ └── OTP (step)
Burada görüldüğü üzere, direct grant flow’un akış mantığı oldukça sadedir… Keycloak’un /token endpoint’ine direct grant flow türünden bir istek geldiği taktirde bu akışın her bir adımı şu sorumlulukları yerine getiriyor olacaktır:
- 1️⃣Username Validation
Gelen istekte username değerini alacak, realm içerisinde ilgili kullanıcıyı arayacak ve ardından bu kullanıcıda şunları kontrol edecektir:
🠒 Kullanıcı var mı?
🠒 Enabled mı?
Eğer başarısız olursa akış HTTP 400 eşliğinde invalid_grant dönecektir. Yok eğer başarılı olursa da user context oluşturulacak ve bir sonraki adıma geçilecektir. - 2️⃣Password
Gelen istekten password değeri alınacak ve kullanıcının stored credential hash’i ile karşılaştırılacaktır. Eğer karşılaştırma gerçekleştirilemiyorsa yine invalid_grant dönecek ve akışı sonlandıracaktır. Yok eğer karşılaştırma başarılıysa kullanıcı authenticate edilmiş sayılacak (ama henüz token üretilmeyecek!) ve bir sonraki adıma geçilecektir. - 3️⃣Direct Grant – Conditional OTP
Bu adım esasında bir sub flow’dur ve aşağıdaki bölümlerden oluşmaktadır:- 3️⃣.1️⃣Condition – user configured
Bu adımdan da anlaşılacağı üzere bir condition execution’dır ve ilgili kullanıcıda OTP credential’ın tanımlı olup olmadığını kontrol etmektedir.Eğer ki OTP yapılandırılmamışsa içinde bulunulan sub flow tamamen atlanacaktır. Yok eğer bir yapılandırma söz konusuysa bir sonraki adıma geçilecektir.
- 3️⃣.2️⃣OTP
Bu adım yalnızca bir önceki condition true olduğu taktirde çalışacaktır. İşlevsel olarak şunları kontrol edecektir:
🠒 Request içerisindetotpparametresi var mı?
🠒 Gönderilen OTP kodu doğru mu?
🠒 Time Step Window geçerli mi?Eğer ki
totpyoksa yahut OTP kodu yanlışsa request başarısız kabul edilecek, aksi taktirde başarılı bir giriş yapılmış olunacaktır…
- 3️⃣.1️⃣Condition – user configured
Şimdi muhtemelen, giriş başarılı olduğu taktirde token’ın üretilmiş olmasını bekliyorsunuz, ancak flow’da hala token üretilmiş değildir! Çünkü dikkat ederseniz token üretimi flow’un bir execution adımı değildir 😉 Flow’dan sonra token Keycloak tarafından üretilecektir…
Direct Grant Flow’da Dikkat Edilmesi Gereken Durumlar
Direct grant flow’u kullanacaksanız başınızın derde girme ihtimalini de değerlendirmeniz gerekmektedir. Haliyle bu değerlendirme sürecini sizlerin acı ve maliyetli tecrübelerine bırakmaksızın bir kaç madde eşliğinde teoride de olsa deneyimlendirerek farkındalığınızı artırmakta fayda görüyorum 🙂
- Client ayarlarına dikkat edin!
Direct grant kullanırken client’ın mutlaka Confidential olması gerekmektedir çünkü bu akışta kullanıcı adı ve şifre doğrudan token endpoint’ine gönderilir; eğer client Public olursa ortada birclient_secretolmadığı için hem uygulama kimliği doğrulanamaz hem de credential’ın kötüye kullanım riski ciddi şekilde artış gösterebilir.Confidential client kullanıldığında ise Keycloak, kullanıcı kimlik bilgilerini doğrulamadan önce client’ı da
client_id+client_secretile doğrular ve böylece hem kullanıcı hem de uygulama tarafı güvence altına alınmış olur. Aksi taktirde public client + direct grant kombinasyonu, özellikle backend yerine istemci tarafında kullanılıyorsa, şifre sızıntısına ve kötüye kullanıma açık bir yapı oluşturabilir. - Direct Grant’ı herkes için açmayın!
Direct grant’i realm genelinde serbest bırakmak, yani varsayılan flow’u değiştirip tüm client’larıngrant_type=passwordile token alabilmesine izin vermek ciddi bir güvenlik riskidir. Çünkü bu durumda özellikle web veya frontend client’lar da kullanıcı adı ve şifreyi doğrudan token endpoint’ine gönderebilir hale gelebilirler. Bu durum, credential sızıntısı ile brute force saldırısı yüzeyini büyütebilir ve risk ihtimallerini ister istemez artırabilir.Brute Force nedir? Brute force, bir saldırganın aynı kullanıcı için sürekli şifre denemesi yapmasıdır. Misal olarak; ahmet / 123456, ahmet / 1234567, ahmet / qwerty, ahmet / 11111 vs. şeklinde…Direct grant’te bu davranış oldukça tehlikeli hal alabilmektedir. Çünkü her şey API çağrısı olarak cereyan ederken bu süreçte login ekranı yok, captcha yok, UI yok… Yani bir script ile saniyede yüzlerce deneme yapılabilmesi mümkündür…
Bu mantıkla, direct grant’i yalnızca gerçekten ihtiyaç duyan ve backend tarafından güvenli şekilde çalışan belirli, confidential client’lar için açık tutmak, diğer web ve public client’larda kapalı bırakmak en doğru yaklaşım olacaktır.
- Brute Force durumuna karşı hazırlıklı olun!
Direct grant akışında login ekranı, captcha ya da kullanıcıyı yavaşlatan herhangi bir görsel engel olmadığı için token endpoint doğrudan otomatik denemelere açık hale gelmektedir. Bu da bir saldırganın script yazarak aynı kullanıcı için ya da farklı kullanıcı adlarıyla hızlıca şifre denemesi yapabilmesine imkan sağlar. İşte bizler bu saldıraya brute force saldırısı diyoruz.Bu farkındalıkla, Keycloak Admin UI üzerinden
Realm🠒Security defenses🠒Brute force detectionkombinasyonuna gelerek brute force’a karşı koruma davranışı mutlaka aktif edilmelidir.
Burada görüldüğü üzere dört farklı yapılandırmayla brute force’a karşı bir davranış belirlenebilmektedir:- Disabled: Brute force koruması kapalıdır. Kullanıcı ne kadar yanlış deneme yaparsa yapsın hesap kilitlenmeyecektir.
- Lockout permanently: Belirlenen başarısız deneme sayısı aşılınca hesap sadece adminin açabileceği şekilde kalıcı olarak kilitlenecektir.
- Lockout temporarily: Limit aşılınca hesap belirli bir süreliğine kilitlenecek, süre dolduğu taktirde otomatik açılacaktır.
- Lockout permanently after temporary lockout: Önce geçici kilitleme uygulanacak, bu durum tekrar ettiği taktirde hesap tamamen kilitlenecektir.
Bizler bu yapılandırmalar sayesinde başarısız deneme eşiğini (failure factor) istediğimiz gibi belirleyebilir ve hatalı denemeler bu eşiği aştığı taktirde ister geçici istersek de kalıcı kilitleme (lockout) uygulayabiliriz.
- MFA beklentisini doğru ayarlayın!
Direct grant akışı, kullanıcı adı ve şifreyi doğrudan API üzerinden alarak token üretmeye yaradığı için yalnızca password ve TOTP gibi basit OTP tabanlı MFA yöntemlerini desteklemektedir. Ancak kullanıcıyı yönlendirme ve ek doğrulama ekranları gerektiren SMS doğrulama, e-posta ile challenge, push notification yahut WebAuthn gibi etkileşimli ve tarayıcı tabanlı ikinci faktörleri çalıştıramamaktadır!Bu nedenle ileride daha gelişmiş veya farklı MFA yöntemlerinin eklenmesi planlanıyorsa eğer direct grant doğru bir tercih olmayacak, onun yerine standart authorization code flow (bknz : Browser Flow Authentication) gibi tarayıcı destekli bir akış kullanmak daha isabetli olacaktır.
- Token süresini kısaltın!
Direct grant genellikle mobil uygulamalar, CLI araçları ve scriptler tarafından kullanıldığı için güvenlik açısından token sürelerinin kısa tutulması önerilmektedir. Özellikle access token ömrü mümkün olduğunca kısa ayarlanmalı, refresh token tarafında ise rotation (her kullanımda yeni refresh token üretme) açık olmalı ve reuse (eski refresh token’ın tekrar kullanılabilmesi) ise kapalı tutulmalıdır. Böylece bir token ele geçirilse bile kısa sürede geçersiz olacak ve yeniden kullanılma riski minimize edilmiş olacaktır. - Scope ve rolleri minimal tutun!
Direct grant ile alınan token’lar doğrudan kullanıcı adı ve şifreyle üretildiği için güvenlik açısından daha hassas kabul edilirler. Bu nedenle, bu token’lara geniş yetkiler vermek hiç de doğru değildir! Özellikle realm-admin gibi yüksek ayrıcalıklı roller ya da full access benzeri geniş scope’lar tanımlanmamalı, bunun yerine sadece gerçekten ihtiyaç duyulan scope ve roller verilerek least privilege prensibi uygulanmalıdır. Yani uzun lafın kısası, direct grant bir anlamda daha riskli bir giriş kapısı olduğu için, üretilen token’ın yetkisi mümkün olduğunca dar tutulmalıdır! - Client credentials ile karıştırmayın!
Direct grant ile client credentials akışları sıkça karıştırılır ancak aralarında temel bir fark vardır: Direct grant’te kullanıcı adı ve şifre gönderilerek cliet tarafından kullanıcı adına token alınır, yani ortada gerçek bir user context vardır. Client credentials’ta ise hiçbir kullanıcı yoktur, sadece client kendi kimliğiyle (client id ve secret) token alır ve bu token uygulamanın kendisini temsil eder. Bu yüzden direct grant user-based authentication içinken, client credentials ise service-to-service iletişim senaryoları için tercih edilir. - Logging & monigoring’e özen gösterin!
Direct grant akışı doğrudan/tokenendpoint’i üzerinden çalıştığı için brute force, credential stuffing ve otomatik saldırılara daha açık bir yüzey oluşturmaktadır. Bu nedenle logging ve monitoring kritik bir öneme sahiptir. Başarısız login denemeleri, olağandışı IP yoğunluğu, kısa sürede çok sayıda token talebi gibi anormallikler loglardan takip edilmeli ve mümkünse SIEM ya da benzeri bir izleme sistemine gönderilerek alarm üretilmelidir. Aksi taktirde saldırılar sessizce gerçekleşebilir ve ancak hasar oluştuğunda fark edilebilir. - HTTPS zorunluluğunu önemseyin!
Direct grant akışında kullanıcı adı ve şifre doğrudan HTTP isteği body’sinde gönderildiği için HTTPS kullanımı tartışmasız şekilde zorunludur. Aksi halde bu bilgiler ağ üzerinde açık metin olarak yakalanabilir ve kullanıcı hesabı yüksek riskle karşı karşıya kalabilir. TLS sayesinde hem kimlik bilgileri hem de dönen access token ve refresh token’lar şifrelenmiş şekilde iletilir, böylece man-in-the-middle ve dinleme saldırılarına karşı temel güvenlik sağlanmış olur. - Legacy mi, geçici mi iyi değerlendirin!
Direct grant günümüzde daha çok legacy ya da geçiş sürecindeki senaryolar için tercih edilen bir akış olarak görülmektedir. Çünkü modern güvenlik yaklaşımı kullanıcıyı doğrudan yetkilendirme sunucusuna yönlendirerek authorization code flow gibi tarayıcı tabanlı ve MFA açısından daha esnek akışları kullanmayı önerir. Bu nedenle, yeni geliştirilen sistemlerde mümkünse browser-based flow tercih edilmeli, direct grant ise gerçekten zorunlu olan durumlarda kontrollü ve sınırlı yetkilerle kullanılmalıdır.
Yani kısaca direct grant flow’u kullanırken neleri yapıp yapmamamız gerektiğini aşağıda şöyle bir tabloda toparlayalım:
| ✅ Yap | ❌ Yapma |
|---|---|
| Confidential client | Frontend’ten direct grant |
| Sadece belirli client’larda aktif | Public client |
| Brute force protection | MFA beklentisi |
| Kısa token süreleri | Geniş yetkiler |
| Minimal yetki | Sınırsız login denemesi |
12 Kritik Soru / 12 Kritik Cevap
Şimdi direct grant flow ile ilgili akla gelebilecek tüm kritik soruları sorup, cevaplandırmaya çalışalım ve böylece konuya dair teferruatları da tamamlayarak teoride tüm yönleriyle incelemeyi tamamlamış olalım.
Soru 1 | Direct Grant Flow tam olarak hangi OAuth2 grant’ine karşılık gelmektedir?
Kullanıcının şifresini doğrudan uygulamaya verdiği ve uygulamanın da bu bilgileri /token endpoint’ine ilettiği Resource Owner Password Credentials Grant’e karşılık gelmektedir.
Not : Resource Owner Password Credentials Grant, OAuth2 dünyasında deprecated kabul edilen bir yaklaşım olsa dahi Keycloak bu yaklaşımı hala kontrollü bir şekilde desteklemektedir.
Soru 2 | Keycloak neden Direct Grant’ı varsayılan olarak ön plana çıkarmaz?
Çünkü; OAuth’un temel amacı şifreyi client’tan saklamaktır. Haliyle direct grant bu ilkeyi bile bile bozmaktadır.
Keycloak, -bu akışı kullanıysan, ne yaptığını biliyorsundur- varsayımıyla hareket etmektedir.
Soru 3 | Direct Grant ile SSO neden mümkün değildir?
Direct grant; stateless çalışmaktadır ve cookie üretmemektedir, ayrıca browser context’i yoktur. Bundan kaynaklı SSO uygulanamamaktadır. Dolayısıyla bu akışla elde edilen token sadece o uygulamaya/client’a aittir.
Soru 4 | Direct Grant ile login olan kullanıcı Keycloak UI’da oturum açmış sayılır mı?
Hayır! Direct grant ile login olunduğunda Keycloak bir access token ve refresh token üretir ancak bu işlem tarayıcı üzerinden gerçekleşmediği için Keycloak tarafından bir browser session (SSO session) oluşturulmaz. Haliyle kullanıcı gerçekten Keycloak login ekranına girip oturum açmış gibi sayılmaz. Bu yüzden Admin Console’daki aktif oturumlar listesinde bir “tarayıcı oturumu” görülemez. Kısaca, direct grant API kullanımı için geçerli bir token verecektir ancak bu Keycloak UI’da açılmış bir oturum anlamına gelmeyecektir. Yani token’ın var olması, browser session’ın var olması demek değildir!
Soru 5 | Direct Grant’te MFA neden sınırlıdır?
Çünkü kullanıcının etkileşime girecek bir ekranı yoktur ve bu nedenle challenge-response yapısı kullanılamamaktadır.
Haliyle direct grant’te TOTP kullanımı mümkünken; SMS, e-mail, Push vs. kullanmak mümkün değildir!
Neden TOTP mümkünde diğerleri değil?
Çünkü TOTP tamamen statik ve senkron bir ikinci faktördür de ondan. Yani kullanıcı, telefonundaki authenticator uygulamasından 6 haneli kodu görebilir ve direct grant isteği sürecinde bu kodu şifreyle birlikte gönderebilir. Bunun için ekstradan bir yönlendirme, challenge başlatma ya da kullanıcıyla etkileşime vs. gerek yoktur!
Ancak SMS, e-posta veya push doğrulama yöntemleri challenge-response mantığıyla çalışmaktadırlar. Önce sunucu bir kod üretecek ve kullanıcıya gönderecektir, kullanıcı o bildirimi görecek ve kimi zaman linke tıklayacak kimi zaman da onay verecektir. Yani süreç ne olursa olsun bir kaç adımlı etkileşim gerektirecektir.
Direct grant’ın yapısal olarak tek bir HTTP isteğinde kullanıcı adı ve şifre (ve varsa OTP) ile token üretmek için tasarlanması; ara adımları, beklemeleri, yönlendirmeleri veya kullanıcı etkileşimlerini barındırmamaktadır. Dolayısıyla SMS/push gibi asenkron ve etkileşimli MFA yöntemlerini teknik olarak çalıştırması mümkün değildir!
Soru 6 | Direct Grant Flow’a custom authentication step eklenebilir mi?
Evet eklenebilir. Misal olarak; custom credential validator, custom OTP check yahut IP / device kontrolü gibi özel adımlar eklenebilir. Ama kullanıcıdan ek bilgi isteyen adımlar eklenemezler.
Soru 7 | Direct Grant neden frontend uygulamalarda kesinlikle önerilmez?
Çünkü, frontend’de direct grant’i kullanmak demek şifreyi istemciye emanet etmek demektir. Haliyle şifre XSS ile çalınabilir ve network log’larında görülebilir.
Soru 8 | Direct Grant ile Client Credentials arasındaki kritik fark nedir?
| Direct Grant | Client Credentials |
|---|---|
| Kullanıcı vardır | Kullanıcı yok |
| Username + password | Client ID + secret |
| User context | App context |
| Riskli | Daha güvenli |
Kullanıcı adına işlem yapıyorsan direct grant, sistem adına yapıyorsan client credentials tercih edilmelidir.
Soru 9 | Direct client ile alınan token revoke edilebilir mi?
Revoke, bir token’ı ya da oturumu geçersiz kılmak yani iptal etmek demektir. Daha önce üretilmiş ve normalde süresi dolana kadar geçerli olması beklenen bir access token’ı veya refresh token’ı, süresi dolmadan önce artık kullanılamaz hale getirmek anlamına gelmektedir.
Keycloak’da direct grant ile alınan token’da tabi ki de revoke edilebilir ancak browser session olmadığı için revoke farkı kullanıcı tarafından hemen hissedilmeyecektir.
Soru 10 | Direct Grant neden ‘geçici çözüm’ olarak görülmelidir?
Çünkü güvenlik modeli zayıfdır. Ayrıca MFA uyumsuzluğu, SSO davranışının olmayışı ve modern yaklaşımlara ters olması bu düşünceyi doğurmaktadır.
Soru 11 | Direct Grant kullanan bir client compromise olursa ne olur?
Direct grant kullanan bir client’ın compromise olması (yani uygulamanın ya da client secret’ının ele geçirilmesi durumunda), ciddi güvenlik riskleri söz konusu olur. Çünkü bu akışta kullanıcı adı ve şifre doğrudan uygulama tarafından alındığı için credential’lar sızabilir, üretilmiş access ve refresh token’lar ele geçirilebilir ve eğer token’lara geniş scope verilmişse sistem içinde büyük yetkiler kötüye kullanılabilir. Bu nedenle direct grant senaryolarında token ömürleri kısa tutulmalı, refresh token güvenliği sıkı ayarlanmalı, client’a minimum yetki verilmeli ve mutlaka etkin bir loglama düzeneği ile izleme yapılmalıdır.
Soru 12 | Direct Grant Flow’da en kritik güvenlik ayarı hangisidir?
Yukarıdaki satırlarda vurgulamaya çalıştığım gibi brute force protection ayarıdır.
Asp.NET Core İle Direct Grant Flow Çalışması
Evet, teoriyi yeterince konuştuk 😊 Artık sıra bu akışı ASP.NET Core üzerinde adım adım, çalışan bir örnekle hayata geçirmeye gelmiştir. Tabi bunun için ilk olarak bir Asp.NET Core uygulaması ile birlikte Keycloak’da aşağıdaki konfigürasyonlarda application-client isimli bir client oluşturulması gerekmektedir.
Dikkat ederseniz direct grant flow için oluşturulacak client’ın sade ve sadece Direct access grants olması yeterlidir. Ancak sizler isterseniz Client authentication‘ı da açabilir ve süreçte client_secret değerini de kullanabilirsiniz.
Hatta bu yaklaşım, mimarisel olarak güvenlik modelini farklı bir yere taşımanıza imkan tanıyabilir. Şöyle ki; client authentication olmaksızın herhangi bir client’tan yanlızca username & password eşliğinde Keycloak’dan token talep edebilirsiniz. Ancak client authentication ile token talebini, kendi oluşturduğunuz bir aracı API’ye yönlendirebilir ve client_id + client_secret ile birlikte direct grant flow’u uygulayabilirsiniz. Böylece token talebinde bulunan client, ister bir backend uygulaması olsun isterse de SPA fark etmeksizin client_secret değerini görmeyecek, bu değer yalnızca özel aracı olarak oluşturulan API’da tutulmuş olacak ve o API üzerinden token talebinde bulunulmuş olacaktır.
Ancak bu durum sizlere çok ideal gibi gelse de bana sorarsanız direct grant flow’u uygulayacağınız çalışmalar da pek önermediğim bir yaklaşımdır. Neden mi? Zaten modern OAuth / OIDC yaklaşımının özellikle kaçınmaya çalıştığı şey kullanıcı şifresinin uygulamalardan uzaklaştırılmasıdır. Haliyle bizler bu yaklaşımı benimsediğimiz taktirde kullanıcı adı ve şifresi yine bizlere ait uygulamanın elinden geçiyor olacaktır ve bu durum zaten istenmeyen vaziyetin ta kendisi olacaktır. Tamam, belki Keycloak’dan token isteyen client’ın kim olduğuna dair biraz daha sıkı çalışma sağlanmış olacak ama güvenlik zincirinin halkasında pek etken olmayacaktır. Hem, direct grant’i kullanıyorsanız eğer zaten doğası gereği güvenlik eksikliği olduğunun farkında olmanız gerekmekte ve bu tarz uğraşlara girmenin pek de lüzumlu olmadığını söylemekte fayda görmekteyim.
Haliyle; direct grant, client authentication ile teoride daha sıkı bir güvenlik sağlıyormuş gibi görünse de pratikte kazanımı oldukça düşük ve hatta gereksiz bir uğraş olacaktır. Eğer gerçekten güvenliği artırmak istiyorsanız direct grant’ten vazgeçip autorization code + PKCE’ye geçmek çok daha doğru bir hamle olacaktır.
Evet, artık Keycloak’da client’ı oluşturduğumuza göre sıra Asp.NET Core uygulamasına gelmiştir. Bu uygulamanın temellerini aşağıdaki kütüphaneler eşliğinde gösterildiği gibi yapılandıralım:
using Microsoft.AspNetCore.Mvc;
using Scalar.AspNetCore;
using Shared.Modals.Request;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
builder.Services.AddHttpClient("keycloak", configure =>
{
configure.BaseAddress = new Uri("http://127.0.0.1:8080");
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.MapScalarApiReference(options =>
{
options.Layout = ScalarLayout.Classic;
options.WithTheme(ScalarTheme.BluePlanet);
});
}
.
.
.
app.Run();
Ve direct grant ile token talebini şöyle bir endpoint ile gerçekleştirelim:
app.MapPost("/login/{realm}", async (LoginRequest loginRequest, IHttpClientFactory httpClientFactory, string realm = "master") =>
{
var httpClient = httpClientFactory.CreateClient("keycloak");
var parameters = new Dictionary<string, string>
{
["grant_type"] = "password",
["client_id"] = "application-client",
//["client_secret"] = "TSQ7dhxgymeqxPunV18S3WQY6dmBY9Il",
["username"] = loginRequest.Username,
["password"] = loginRequest.Password
};
var response = await httpClient.PostAsync($"realms/{realm}/protocol/openid-connect/token", new FormUrlEncodedContent(parameters));
if (!response.IsSuccessStatusCode)
return Results.Unauthorized();
var token = await response.Content.ReadFromJsonAsync<Shared.Modals.Responses.AccessTokenResponse>();
return Results.Ok(token);
});
İşte bu kadar 🙂 Şu ana kadar tüm risklerini aktarmaya çalıştığım bu akış esasında bu kadar basit bir şekilde uygulanabilen bir yaklaşıma sahiptir. Ve evet, bu endpoint’e gerekli bilgiler doğrultusunda istekte bulunulduğu taktirde aşağıdaki gibi token elde ediliyor olacaktır.
Tabi şu andaki durumuyla ilgili client her türlü saldırıya açık vaziyettedir. Haliyle bu realm’de direct grant flow kullanıldığı için brute force protection‘ın açılmasını ve rate limiting‘in uygulanmasını tavsiye ederim. Ayrıca şu aşamadan sonra sistemi en kötü ihtimal loglarla takip etmeyi ihmal etmemek gerekmektedir…
Token İle API’yi Koruyalım…
Evet, bunun için ekstradan bir Asp.NET Core projesi oluşturmaya gerek görmemekteyim. Mevcut uygulamamızda bir endpoint’i korumalı hale getirebilir ve doğrulamayı gerçekleştirebiliriz.
Şimdi bunun için mevcut uygulamada aşağıdaki gibi authentication ve authorization yapılandırmalarında bulunalım:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.Authority = "http://127.0.0.1:8080/realms/master";
options.Audience = "account";
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
NameClaimType = JwtRegisteredClaimNames.PreferredUsername
};
});
builder.Services.AddAuthorization();
.
.
.
var app = builder.Build();
app.UseAuthentication()
.UseAuthorization();
.
.
.
app.Run();
Ardından aşağıdaki gibi korumalı bir endpoint tasarlayalım:
app.MapGet("/profile", (HttpContext httpContext) =>
{
return Results.Ok(new
{
httpContext.User.Identity?.Name,
Claims = httpContext.User.Claims.Select(claim => new { claim.Type, claim.Value })
});
}).RequireAuthorization();
İşte tamamdır… Artık token edinmeksizin bu endpoint’e istekte bulunulamayacaktır. Tabi bunun testini sizlere bırakıyor ve bu içeriği artık noktalıyorum 🙂
Nihai olarak;
Bu içeriğimizde direct grant flow’un tam teferruatlı incelemiş ve nedir, nasıl yapılırdan ziyade genel çizginin dışına çıkarak ilgili flow’u dikkat edilmesi gereken hususlar doğrultusunda ciddi bir araştırma ve inceleme sürecine tabi tutmuş bulunmaktayız.
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Teşekkürler kardeşim eline sağlık güzel bir çalışma olmuş.